东南大学算法设计与分析复习题.docx
- 文档编号:6275621
- 上传时间:2023-01-05
- 格式:DOCX
- 页数:16
- 大小:33.40KB
东南大学算法设计与分析复习题.docx
《东南大学算法设计与分析复习题.docx》由会员分享,可在线阅读,更多相关《东南大学算法设计与分析复习题.docx(16页珍藏版)》请在冰豆网上搜索。
东南大学算法设计与分析复习题
什么是最坏情况时间复杂性?
什么是平均情况时间复杂性?
答:
最坏情况时间复杂性是规模为n的所有输入中,基本运算执行次数为最多的时间复杂性。
平均情况时间复杂性是规模为n的所有输入的算法时间复杂度的平均值(一般均假设每种输入情况以等概率出现)。
什么是相互独立的函数序列?
何时称函数项μk(x)能被其它函数项线性表出?
答:
设{μ0(x),μ1(x),μ2(x),...,μn(x),...}是某一数域上的函数序列,(x的值以及μk(x)(k=0,1,2,⋯)的值都在同一个数域中)任取μk(x)(k=0,1,2,⋯),不存在数域中的数α1,α2,⋯,αp,使得μk(x)=α1μi1(x)+α2μi2(x)+⋯+αpμip(x),即任何一个函数项μk(x)不能被其它函数项线性表出。
根据特征根的情况,常系数线性递归方程的解有哪几种不同的形式?
答:
1.若方程(**)恰有r个互不相同的特征根α1,α2,⋯,αr(即i≠j时有αi≠αj),则齐次方程(*)的解为an=A1+A2+⋯+Ar(齐通解,即齐次方程的通解)(A1~Ar为待定系数,可由r个连续的边界条件唯一确定)
2.若α1,α2是(**)方程的一对共扼复数根ρ和ρ,eiθeiθ.则这两个根对应的解的部分为Aρncos(nθ)+Bρnsin(nθ)(A,B为实的待定系数)
3.若α是(**)方程的k重根,则α对应的解的部分为C1αn+C2nαn+C3n2αn+⋯+Cknk-1αn(C1~Ck为待定常数)
4.若(*)方程中的f(n)≠0(非齐次),且q(n)是(*)的一个解,则(*)方程的解为:
(*)的齐通解(含有待定系数)+q(n)(非齐特解),(齐通解中的待定系数由边界条件唯一确定)
求和中的通项与积分中的被积函数之间有什么样的关系?
答:
求和中的通项的表达形式一般就是被积函数,一般用放缩的方法求得通项得上下界。
分治法求最大、最小元算法的主要思想?
答:
当n=2时,一次比较就可以找出两个数据元素的最大元和最小元。
当n>2时,可以把n个数据元素分为大致相等的两半,一半有n/2个数据元素,而另一半有n/2个数据元素。
先分别找出各自组中的最大元和最小元,然后将两个最大元进行比较,就可得n个元素的最大元;将两个最小元进行比较,就可得n个元素的最小元。
求最大、最小元算法的时间复杂度(比较次数)下界是多少?
分治算法在什么情况下可以达到下界?
答:
在规模为n的数据元素集合中找出最大元和最小元,至少需要3n/2-2次比较,即3n/2-2是找最大最小元算法的下界。
当n=2k,或当n≠2k时,若n是若干2的整数幂之和,(e.g.42=32+8+2),
则算法的时间复杂度仍可达到3n/2-2。
如何用分治法求两个n位二进制数x和y的乘积?
算法的时间复杂度是多少?
答:
若n=2k,则x可表为a2n/2+b,y可表为c2n/2+d(如图),其中a,b,c,d均为n/2位二进制数。
于是x*y=(a2n/2+b)(c2n/2+d)=ac2n+(ad+bc)2n/2+bd,计算式ac2n+(ad+bc)2n/2+bd中的ad+bc可写为:
而(ad+bc)=(a+b)(d+c)-ac-bd,因此在ac和bd计算出之后,只要再做4次加减法,一次(n/2位数的)乘法就可以计算出ad+bc。
而原来计算(ad+bc)需要做2次乘法、一次加法;新的计算公式比原方法少做了一次乘法。
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 当si=m时将si放入数组S2; 当si>m时将si放入数组S3; 在得到的3个集合中,S1中的数均小于m; S2中的数均等于m;S3中的数均大于m。 6.按照k值大小,共可分成下列三种情况(注意S2至少有一个元素m): k≤|S1|;|S1| 下面针对这三种情况分别进行讨论。 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| 因为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 则称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≤ 递推求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 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]]为"No"then/*作业D[k]放在当前最左空位*/{F[i]←D[k];i增1;E[D[k]]置为"Yes"}} elseifE[-D[k]]为"No"then/*作业-D[k]放在当前最右空位*/{F[j]←-D[k];j减1;E[-D[k]]置为"Yes"}} 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']+Weight[v']=Depth(v)+1。 由上述两式可得: 新Weight[r']=Depth[v]+1-Weight[v']+旧Weight[r']。 由于Tr中的其它各结点相对于r'的位置合并后均未改变, 故Tr中的其它各结点的Weight值无需改变, 只要r'的新Weight值正确, 则Tr中的其它各结点就都能够正确计算出其在原森林中的高度。 2、Count[v'] 合并后应有: 从r到s的权和+新的Weight[r']=Depth(v)+1。 故有新的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.随机算法避免了去构造最坏情况的例子。 最坏情况虽有
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 东南大学 算法 设计 分析 复习题