东南大学算法设计与分析复习题文档格式.docx

上传人:b****5 文档编号:19283141 上传时间:2023-01-05 格式:DOCX 页数:16 大小:33.40KB
下载 相关 举报
东南大学算法设计与分析复习题文档格式.docx_第1页
第1页 / 共16页
东南大学算法设计与分析复习题文档格式.docx_第2页
第2页 / 共16页
东南大学算法设计与分析复习题文档格式.docx_第3页
第3页 / 共16页
东南大学算法设计与分析复习题文档格式.docx_第4页
第4页 / 共16页
东南大学算法设计与分析复习题文档格式.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

东南大学算法设计与分析复习题文档格式.docx

《东南大学算法设计与分析复习题文档格式.docx》由会员分享,可在线阅读,更多相关《东南大学算法设计与分析复习题文档格式.docx(16页珍藏版)》请在冰豆网上搜索。

东南大学算法设计与分析复习题文档格式.docx

T(n)=3T(n/2)+Θ(n),即a=3,b=2,f(n)=Θ(n)。

此时有:

==naLogbn32Logn1.59,并仍有f(n)=O(),ε−)(aLogbn于是有T(n)=Θ(n1.59),比Θ(n2)要好不少。

用200字概括Select(求第k小元)算法的主要思路。

1.若S<

50,则采用堆排序的方法找出第k小的元素

2.将n个元素分成[n/5]组,每组5个元素

3.对每个5元组进行排序,全部5元组排序后,从每组中取出第3个元素(中间元)得到一个长为[n/5]的数组M

4.递归调用Select([|M|/2],M),即在M数组中找到第[|M|/2]小的数(中位数),记为m

5.依次扫描整个数组S,此项工作所需时间为O(n)。

当si<

m时将si放入数组S1;

当si=m时将si放入数组S2;

当si>

m时将si放入数组S3;

在得到的3个集合中,S1中的数均小于m;

S2中的数均等于m;

S3中的数均大于m。

6.按照k值大小,共可分成下列三种情况(注意S2至少有一个元素m):

k≤|S1|;

|S1|<

k≤|S1|+|S2|;

以及k>

|S1|+|S2|。

下面针对这三种情况分别进行讨论。

6.a:

若k≤|S1|,则第k小元素必定在S1中。

此时递归调用Select(k,S1),就可以获得第k小元素。

因大于等于m的数据元素至少有3n/10-6个,而S1中的数均小于m,故S1中的数据元素至多有7n/10+6个,即|S1|≤7n/10+6。

因此,调用Select(k,S1)的时间复杂度不超过T(7n/10+6)。

6.b:

若|S1|<

k≤|S1|+|S2|,则第k小元素必定在S2中。

因为S2中的元素的值均等于m,故第k小元素就是m。

由于答案已经得到,此时立刻返回第k小元素m。

这部分工作的时间复杂度为O

(1)。

6.c:

若k>

|S1|+|S2|,则第k小元素必定大于m,因此在S3中。

而且此时该元素在S3中应为第k-|S1|-|S2|小的元素。

于是递归调用Select(k-|S1|-|S2|,S3),就可以获得S中的第k小元素。

因小于等于m的数据元素至少有3n/10-6个

1的情况下,T(n)分别为什么?

≥1及p+q<

时间复杂度为T(n)=T(p*n)+T(q*n)+a*n时,在p+q

T(n)≤a*n*∑k=0∞(p+q)k

矩阵相乘算法目前最好的时间复杂度是多少?

目前矩阵乘法最好的时间复杂度是能做到O(n2.376)

叙述Strassen矩阵相乘算法的主要思路和意义。

把矩阵A,B分成4个规模为n/2的子矩阵快

C11=A11B11+A12B21,C12=A11B12+A12

C21=A21B11+A22B21,C22=A21B12+A22B22

同时引入下列Mi(i=1,2...7)

则计算两个n阶矩阵的乘法为7对n/2阶矩阵的乘法(时间为7T(n/2)),以及18对n/2阶矩阵的加减法则递归方程为T(n)=7T(n/2)+Θ(n2),由主定理得T(n)=Θ(n2.81).Strassen矩阵相乘算法意义在于打破了人们认为矩阵乘法得时间复杂度为Θ(n3)得固定看法。

什么是最长公共子序列问题?

在求LCS的算法中,C[i,j]是如何计算的?

为什么需要这样计算?

若Z<

X,Z<

Y,且不存在比Z更长的X和Y的公共子序列,

则称Z是X和Y的最长公共子序列,记为Z∈LCS(X,Y)。

如何在低于指数级的时间复杂度内找到LCS称为最长公共子序列问题

C[i,j]=0,若i=0或j=0

C[I,j]=C[i-1,j-1]+1若i,j>

0且xi=yi

C[I,j]=max{C[i-1,j],C[i,j-1]}若i,j>

0且xi!

=yi

二维数组C,用C[i,j]记录Xi与Yj的LCS的长度如果我们是自底向上进行递推计算,那么在计算C[i,j]之前,C[i-1,j-1],C[i-1,j]与C[i,j-1]均已计算出来。

此时我们根据X[i]=Y[j]还是X[i]≠Y[j],就可以计算出C[i,j]。

计算的理由:

求LCS(Xm-1,Y)的长度与LCS(X,Yn-1)的长度这两个问题不是相互独立的:

∵两者都要求LCS(Xm-1,Yn-1)的长度,因而具有重叠性。

另外两个序列的LCS中包含了两个序列的前缀的LCS,故问题具有最优子结构性质考虑用动态规划法。

用200~300字概述求最优二分搜索树算法的主要步骤。

算法中有哪几点最为关键?

记cij是最优子树Tij的耗费,则ci,k-1是最优子树Ti,k-1的耗费,ck,j是最优子树Tk,j的耗费。

考察以ak(i+1≤k≤j)为根、由结点bi,ai+1,bi+1,⋯,aj,bj构成的、耗费最小的树的总耗费:

该树的左子树必然是Ti,k-1,右子树必然是Tk,j。

这棵树的总耗费可分为三部分:

左子树、右子树和根。

由于Ti,k-1作为左子树接到结点ak之下时,其耗费增加wi,k-1,故左子树的耗费为:

ci,k-1+wi,k-1,同理,右子树的耗费为:

ck,j+wk,j,由于根ak的深度为0,按定义,根的耗费为pk。

因此,以ak为根、耗费最小的树的总耗费为:

ci,k-1+wi,k-1+ckj+wk,j+pk。

注意到,wi,k-1=qi+pi+1+qi+1+⋯+pk-1+qk-1,wk,j=qk+pk+1+qk+1+⋯+pj+qj,从而有wi,k-1+wkj+pk=qi+pi+1+qi+1+⋯+pk-1+qk-1+pk+qk+pk+1+qk+1+⋯+pj+qj=wij。

由此得到以ak为根、耗费最小的树的总耗费为:

ci,k-1+ckj+wi,j

由于pi(i=1,2,⋯,n),qj(j=0,1,2,⋯,n)在初始时已经知道,若wi,j-1已知,则根据wi,j=wi,j-1+pj+qj可以计算出wij。

故当ci,k-1与ckj已知时,以ak为根的树的最小总耗费在O

(1)时间就可以计算出来。

分别计算以ai+1,ai+2,⋯,aj为根、含有结点bi,ai+1,bi+1,⋯,aj,bj的树的最小总耗费,从中选出耗费最小的树,此即最优子树Tij。

因此,最优子树Tij的耗费cij={cminjki≤<

jki≤<

i,k-1+ckj+wij}。

递推求cij及记录Tij的根的算法

本算法的关键点:

分析出最优二分搜索树具有最优子结构;

在计算中规模较小的最优子树在计算中要被多次用到。

Cij和Wij都是可以通过前面的计算递推得出的。

有了Tij的根的序号后,如何构造出最优二分搜索树?

设Tij的根为ak(rij记录到的值是k),则从根开始建结点。

Build-tree(i,j,r,A)/*建立最优子树Tij*/

{Ifi≥jreturn"

nill"

;

pointer←newnode(nodetype);

k←rij;

/*必有i<

m≤j*/

pointer→value←A[k];

/*A[k]即ak*/

pointer→leftson←Buildtree(i,k-1,r,A);

/*建立最优左子树Ti,k-1*/

pointer→rightson←Buildertree(k,j,r,A);

/*建立最优右子树Tk,j*/

returnpointer;

}

FrancisYao的办法为什么会把算法时间复杂度从O(n3)降到O(n2)?

Th:

如果最小耗费树Ti,j-1和Ti+1,j的根分别为ap和aq,则必有

⑴p≤q⑵最小耗费树Tij的根ak满足p≤k≤q。

(证明略。

有了上述定理,我们无需在ai+1~aj之间去一一尝试,使得找到的ak为根时,{ci,k-1+ckj+wij}为最小,而只要从ap~aq之间去找一个根即可。

算法时间复杂度为Θ(n2)的证明:

首先注意Ti,j-1和Ti+1,j的规模恰好比Ti,j小1。

由于算法是按树中结点的个数(即规模)从小到大计算的,故在计算rij时,ri,j-1(即定理中的p)和ri+1,j(即定理中的q)

都已经计算出来了。

一般地,设含有k个连续结点的最优二分搜索子树的根

r0k,r1(k+1),⋯,r(n-k),n已经计算出来。

由Th知,含有k+1个连续结点的最优二分搜索子树Ti,i+k+1的根必在ri,i+k与ri+1,i+k+1之间。

故r0,k+1在r0,k与r1,k+1之间,求出r0,k+1的搜索区间长度为r1,k+1-r0,k;

r1,k+2在r1,k+1与r2,k+2之间,求出r1,k+2的搜索区间长度r2,k+2-r1,k+1;

r2,k+3在r2,k+2与r3,k+3之间,求出r2,k+3的搜索区间长度r3,k+3-r2,k+2;

⋯⋯r(n-k-1),n在r(n-k-1),n-1与r(n-k),n之间,

求出r(n-k-1),n的搜索区间长度为r(n-k),n-r(n-k-1),n-1;

于是,求出所有规模为k+1的最优二分搜索子树的根

r0,k+1,r1,k+2,⋯,r(n-k-1),n的搜索长度的总和=

(rn-k,n-rn-k-1,n-1)+⋯+(r3,k+3-r2,k+2)+(r2,k+2-r1,k+1)+(r1,k+1-r0,k)=r(n-k),n-r0,k

∵rn-k,n最多为n,r0,k最小为1,

∴搜索区间长度最多为Θ(n),即第2层循环执行总次数为Θ(n),

因此算法总的时间复杂度为Θ(n2)。

用200~300字概述二维流水作业调度算法的主要步骤

求解该问题的算法如下。

1.建立长为2n的数组C,将a1,a2,┅,an依次放入C[1]~C[n]中,b1,b2,┅,bn依次放入C[n+1]~C[2n]中。

/*O(n),下面将对这2n个数进行排序*/

2.对长为2n的数组D进行初始化:

D[1]~D[n]中依次放1,2,┅,n,D[n+1]~D[2n]中依次放-1,-2,┅,-n。

/*O(n),分别对应于a1,a2,┅,an和b1,b2,┅,bn的下标*/

3.对数组C进行排序,D[k]始终保持与C[k]的对应关系。

(若C[i]与C[j]对换,则D[i]也与D[j]对换。

或将C,D放在同一结构体中。

)当a1,a2,┅,an及b1,b2,┅,bn按从小到大次序排好之后,

D[1]~D[2n]也就按从小到大的次序记录了这些ai和bj的下标即作业号(bj的下标前有一负号以区别于ai))。

/*O(nlogn)*/

4.将E[1]~E[n]全部置为"

No"

/*O(n),表示所有任务均尚未被安排*/

5.下标变量初始化:

i←1;

j←n;

k←1;

/*O

(1),i指向当前最左空位F[i],放当前应最先安排的作业号;

*//*j指向当前最右空位F[j],放当前应最后安排的作业号;

*//*k从1开始逐次增1,*//*D[k](或-D[k])按ai和bj从小到大的次序依次给出作业号*/

6.whilei≤j

do{/*作业尚未安排完毕,i从小到大,j从大到小*/

ifD[k]>

0then{ifE[D[k]]为"

then/*作业D[k]放在当前最左空位*/{F[i]←D[k];

i增1;

E[D[k]]置为"

Yes"

}}

elseifE[-D[k]]为"

then/*作业-D[k]放在当前最右空位*/{F[j]←-D[k];

j减1;

E[-D[k]]置为"

}}

k增1;

}

什么是备忘录方法?

它在什么情况下使用较为有效?

若有大量的子问题无需求解时,用备忘录方法较省时。

但当无需计算的子问题只有少部分或全部都要计算时,

用递推方法比备忘录方法要好(如矩阵连乘,最优二分搜索树)。

简单不相交集的合并算法中为什么要引进集合的外部名和内部名?

若没有内部名,

则每次合并时两个集合中的所有元素均要改名(改为K),

这样,在n-1次Union中改名的时间就变为O(n2)。

什么是平摊分析?

平摊分析常用的手法有哪几种?

简单说明这几种手法的要点。

考虑n条指令执行的最坏时间复杂性。

即使某些指令执行时具有比较大的代价,

但利用平摊分析后对整体考虑,可以得到较小的平均代价。

平摊分析方法主要有:

聚集方法,会计方法和势能方法。

聚集方法:

全局考虑时间复杂性,把n条指令的耗费分为几类;

分别计算每一类耗费的总和,然后再把各类耗费总加起来。

会计方法:

利用几个操作之间的联系,在一个操作中预先支付下面某个操作的费用,以达到简化代价计算的目地。

势能方法:

设Ci为第i个操作的实际代价,

D0为处理对象的数据结构的初始状态,

Di为第i个操作施加于数据结构Di-1之上后数据结构的状态,

引入势函数Φ,Φ(Di)是与Di相关的势。

定义第i个操作的平摊代价为:

=Ci+(Φ(Di)-Φ(Di-1))(即实际代价加上势的变化),

为什么树结构下执行O(n)条带路径压缩的Union-Find指令只需要O(n*G(n))时间?

用平摊分析的聚集方法,把O(n)条Find指令的耗费分为三类:

1)O(n)条Find指令的根费用,

2)O(n)条Find指令的组费用,

3)O(n)条Find指令的路径费用。

根费用:

执行一条Find指令时,处理根及其儿子所需的费用。

一条Find指令只会碰到一个根(及其儿子),故O(n)条Find指令的根费用为O(n),这样,根及其儿子的费用已全部计算在内。

组费用:

若结点ik(0≤k≤m-2)与其父结点ik+1的秩不在同一个秩组中,则对ik收取一个组费用。

因最多有G(n)个组,故一条Find指令最多只会碰到G(n)个结点、其秩与其父结点的秩不在同一个秩组中,故O(n)条Find指令的组费用最多为O(n*G(n))。

路径费用:

由于其秩在组号为g的组中结点的个数不超过n/F(g),故组g中的结点的收取的路径费用不超过[n/F(g)]*[F(g)-(F(g-1)+1)]<

[n/F(g)]*F(g)=n。

因总共只有G(n)个组,故所有结点在O(n)条Find指令的执行中,收取的路径费用不超过O(n*G(n))。

三项费用总加起来,有O(n)+O(n*G(n))+O(n*G(n))=O(n*G(n))于是可得结论:

如果合并是是把小集合并入大集合,且执行Find指令时实施路径压缩,则执行O(n)条Unoin-Find指令的时间复杂度为O(n*G(n));

树结构下执行O(n)条带路径压缩的Union-Find指令能否降到线性即O(n)时间?

执行O(n)条Unoin-Find指令时,对于任意的c,都存在一个特殊的Unoin-Find指令序列,

使得执行该序列的时间复杂度>

cn,即算法在最坏情况下不是线性的。

用200~300字概述Link(v,r)程序的执行过程。

该程序的要点在什么地方?

要点在于:

为保持Weight的性质,合并的同时要对Weight[r'

]进行修改。

(由于原先的Link就是把r接到v之下,而含有v的树中各结点的深度并未受到任何影响,现在把Tr接在v'

之下,Tv中的各结点当然也不会受到任何影响,故Tv树中各结点的Weight值无需修改。

)Tr树中各结点的Weight值如何修改?

设用Find-Depth指令可以查到v的深度为Depth(v),

(注意Depth(v)是Find-Depth指令的返回值而不是函数)而在原先的森林中,由于r是根,故原先有Depth(r)=0(也是值)。

执行Link指令后,把r作为v的儿子,

则此时在原先的森林中,r的深度为Depth(v)+1。

设在D-森林中,r'

的儿子是s。

由Weight的性质,在D-森林中的2棵树合并之前,有:

从r到s路径上各结点的权和+旧Weight[r'

]=0(r在原森林中的深度)

D-森林中的2棵树合并之后,在原先森林中r的深度为

从r到s的权和+新Weight[r'

]+Weight[v'

](按Weight的性质),

另一方面,按上述分析,在原先森林中r的深度为Depth(v)+1,

故有从r到s的权和+新Weight[r'

]=Depth(v)+1。

由上述两式可得:

新Weight[r'

]=Depth[v]+1-Weight[v'

]+旧Weight[r'

]。

由于Tr中的其它各结点相对于r'

的位置合并后均未改变,

故Tr中的其它各结点的Weight值无需改变,

只要r'

的新Weight值正确,

则Tr中的其它各结点就都能够正确计算出其在原森林中的高度。

2、Count[v'

]<

Count[r'

]时,把v'

作为r'

的儿子。

合并后应有:

从r到s的权和+新的Weight[r'

故有新的Weight[r'

]=Depth(v)+1+旧Weight[r'

另外,Weight[v'

]也要修改。

设在D-森林中,v'

的儿子是t,则合并前有:

从v到t的权和+旧Weight[v'

]=Depth(v)(v在原森林里的深度)。

而合并以后应有:

从v到t的权和+新Weight[v'

]+新Weight[r'

]=Depth(v)(合并时是将r接到v之下,故v在原森林里的深度并不改变。

)2式联立得新Weight[v'

]=旧Weight[v'

]-新Weight[r'

不论哪一种情况,权修改完后都要将新根的Count值改为Count[v'

]+Count[r'

Link程序中,除了Find-Depth(v)(以找到根v'

并计算出Depth(v))、Find(r)(以找到根r'

)外,其余部分的执行时间是常数,而Find-Depth的时间复杂度与Find的同阶,故O(n)条Link和Find-Depth可以在O(n*G(n))里完成。

你认为脱线MIN算法的关键点在什么地方?

算法:

fori=1tondo{

j←FIND(i);

ifj=0then{输出"

i未在序列中出现"

elseifj>

kthen{输出"

i未被删除"

else{/*i确实被删除了*/

输出"

i被第j条E指令所删除"

UNION(j,Succ[j],Succ[j]);

Succ[Pred[j]]←Succ[j];

/*集合j不再存在*/

Pred[Succ[j]]←Pred[j]

}}

算法最关键的在于集合的Union和find算法的使用。

比较LasVegas算法和MonteCarlo算法,它们有什么相同和相异之处?

随机算法有哪些优点?

LasVegas算法总是给出正确的结果,

但在少数应用中,可能出现求不出解的情况。

此时需再次调用算法进行计算,直到获得解为止。

对于此类算法,主要是分析算法的时间复杂度的期望值,以及调用一次产生失败(求不出解)的概率。

MontCarlo算法通常不能保证计算出来的结果总是正确的,一般只能断定所给解的正确性不小于p(<p<1=。

通过算法的反复执行(即以增大算法的执行时间为代价),能够使发生错误的概率小到可以忽略的程度。

由于每次执行的算法是独立的,故k次执行均发生错误的概率为(1-p)k。

随机算法的优点:

1.对于某一给定的问题,随机算法所需的时间与空间复杂性,往往比当前已知的、最好的确定性算法要好。

2.到目前为止设计出来的各种随机算法,无论是从理解上还是实现上,都是极为简单的。

3.随机算法避免了去构造最坏情况的例子。

最坏情况虽有

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1