算法分析与设计部分复习题答案.docx

上传人:b****7 文档编号:9080043 上传时间:2023-02-03 格式:DOCX 页数:8 大小:23.51KB
下载 相关 举报
算法分析与设计部分复习题答案.docx_第1页
第1页 / 共8页
算法分析与设计部分复习题答案.docx_第2页
第2页 / 共8页
算法分析与设计部分复习题答案.docx_第3页
第3页 / 共8页
算法分析与设计部分复习题答案.docx_第4页
第4页 / 共8页
算法分析与设计部分复习题答案.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

算法分析与设计部分复习题答案.docx

《算法分析与设计部分复习题答案.docx》由会员分享,可在线阅读,更多相关《算法分析与设计部分复习题答案.docx(8页珍藏版)》请在冰豆网上搜索。

算法分析与设计部分复习题答案.docx

算法分析与设计部分复习题答案

算法设计与分析复习题1、一个算法应有哪些主要特征?

有限性、确定性、输入、输出、可行性2、分治法(DivideandConquer)与动态规划(DynamicProgramming)有什么不同?

分治法是将一个问题划分成一系列独立的子问题,分别处理后将结果组合以得到原问题的答案。

动态规划同样将一个问题划分成一系列子问题进行处理,但当子问题不是互相独立而是互有联系时,动态规划不会重复计算子问题间联系的问题,是更高效的解决办法。

(具体解释太长了这个答案可以得点分)3、试举例说明贪心算法对有的问题是有效的,而对一些问题是无效的。

贪心算法的思想是通过选择局部最优以求得最优解,但某些最优解问题无法由局部最优推出,如0-1knapsackproblem(背包问题,一个能装20斤的背包装入一定商品,要求价值最高)4、求解方程f(n)=f(n-1)+f(n-2),f

(1)=f

(2)=1。

nn15151(斐波那契数列)f(n)225(证明太复杂了不贴了)k5、求解方程T(n)=2T(n/2)+1,T

(1)=1,设n=2。

T(n)=2*(2*T(n/4)+1)+1=2*(2*(T(n/8)+1)+1)+1推出以下方程kk1kT(n)212...2(n1且n2)kkk13n121221kkT(n)2(n1且n2)222证明用数学归纳法。

voidmax_min(inta[],intm,intn,int*min)//运用分治法查找最大值与最小值{intmiddle,hmin,gmin;if(m==n){*min=a[m];}elseif(m==n-1){if(a[m]>a[n]){

*min=a[n];}else{*min=a[m];}}else{middle=(m+n)/2;max_min(a,m,middle,&gmin);max_min(a,middle+1,n,&hmin);if(gmin

此为伪代码不可运行,由小到大排序,比较简单就不写注释了QSort(Array,Len){if(len<2)return;left=0;right=Len-1;mid=(left+right)/2;while(leftArray[mid])right--;if(left

elseif(right==mid)mid=left;left++;right--;}}QSort(Array,mid);QSort(Array+mid+1,Len-mid-1);}最坏时间复杂度为O(n^2)(每次选中的中间元素为序列的最小或最大元T(n)=T(n-1)+T(0)+O(n))最好时间复杂度为O(nlogn)(每次选中的中间元素为序列的正中元素T(n)<=2T(n/2)+O(n))平均时间复杂度为O(nlogn)(不会分析„„)7、利用QuickSorting的原理,编写一个查找第k小元素的算法。

此为伪代码不可运行intQSort(Array,Len,k){if(k>len)return-1;//没有第k个元素left=0;right=Len-1;mid=(left+right)/2;while(leftArray[mid])right--;if(leftk-1)QSort(Array,mid,k);//第k小元在mid之前则在mid之前继续查找第k小元elseif(mid

此为伪代码不可运行,由小到大排序//主函数

heapsort(Array,Len){//建堆for(i=Len/2-1;i>=0;i--){heapify(Array,i,Len);}//排序for(i=Len-1;i>0;i--){temp=Array[0];Array[0]=Array[i];Array[i]=temp;heapify(Array,0,i);}}//建成的堆根为最大元素这样排序后数组会变为由小到大排序heapify(Array,root,Len){parent=root;//父节点temp=Array[root];for(child=parent*2+1;child=Array[child])break;//子节点大于父节点子节点上提父节点下沉并继续与下层子节点比较看是否仍需下沉Array[parent]=Array[child];parent=child;}Array[parent]=temp;}时间复杂度为O(nlogn),heapify()的时间复杂度为O(logn)9、编写一个算法,可以检测一个字符串是否回文(如:

afaddafa,abwba等)。

boolpalindrome(Array,Len){if(Len<1)returnfalse;//第一个字母与最后一个字母比较//第二个字母与倒数第二个字母比较//第三个字母与倒数第三个字母比较。

i=0;j=Len-1;while(i

{if(Array[i]!

=Array[j])returnfalse;i++;j--;}returntrue;}10、如果是检测一个字符串中是否包含一个回文子串,应如何编写算法。

如果是找最大的回文子串呢?

//是否包含一个回文子串boolsub_palindrome(Array,Len){for(i=0;i

=Array[j])&&(j>i))j--;if(j!

=i){if(palindrome(Array+i,j-i+1)==true)returntrue;}}}//寻找最大回文子串当返回的RLen不为0时Result为回文起点指针RLen为回文长度max_sub_palindrome(Array,Len,&Result,&RLen){RLen=0;for(i=0;ii)&&(Array[i]!

=Array[j]))j--;if(j!

=i){if(palindrome(Array+i,j-i+1)==true){if(j-i+1>RLen){RLen=j-i+1;Result=Array+i;}}}}}

//子函数boolpalindrome(Array,Len){if(Len<2)returnfalse;i=0;j=Len-1;while(i

=Array[j])returnfalse;i++;j--;}returntrue;}11、设n个不同的整数排好序后存在数组T[1:

n]中。

若存在一个下标i,使得T[i]=i,设计一个有效的算法找到该下标。

要求时间复杂性是O(logn)。

因为整数数组已排好序,可以从数组的正中元素开始寻找T[i],当T[(n+1)/2]>(n+1)/2时,要求的i一定在T[1:

(n+1)/2-1]中,当T[(n+1)/2]<(n+1)/2时,要求的i一定在T[(n+1)/2+1:

n]中,递归地使用此方法。

//初始Left=1Right=nintfind_i(T,Left,Right){if(Left>Right)return-1;(Left+Right)/2if(T[(Left+Right)/2]>(Left+Right)/2)returnfind_i(T,(Left+Right)/2+1,Right);if(T[(Left+Right)/2]<(Left+Right)/2)returnfind_i(T,Left,(Left+Right)/2-1);elsereturn(Left+Right)/2;}12、编写一个采用KMP的算法查找T的子串P,并判断匹配失败的字符是否在P中,以此确定可滑动的最大距离。

比普通KMP多一句判断,但是效率要低很多,更好的办法是用字母表,先遍历一遍子串,将子串中有的字母标记为1,但这样限制了字符串的类型(只能是字母数字,中文日文就不行了),如果有很好的办法麻烦告诉一下//辅助函数用于创建子串的next数组char*get_next(charP[]){inti=0,k=-1;next=newchar[strlen(P)];//创建next数组//具体解释见书next[0]=-1;while(i<(int)strlen(P)-1)

{//这里为了方便理解将原来的判断语句拆开来写了效率更低//k为-1说明与子串第一个字符匹配失败if(k==-1){i++;k=0;next[i]=0;}//匹配成功elseif(P[i]==P[k]){i++;k++;next[i]=k;}//匹配失败elsek=next[k];}}//主函数返回子串P在T中第一次出现的位置返回-1表示P未在T中出现intKMP(char*T,char*P){//获得子串的next数组next=get_next(P);inti=0,k=0;//具体解释见书while((i<(int)strlen(T))&&(k<(int)strlen(P))){//k为-1说明与子串第一个字符匹配失败if(k==-1){i++;k=0;}//匹配成功elseif(T[i]==P[k]){i++;k++;}//匹配失败else{

//此处为多加的一个判断IsInString(P,T[i])判断字符T[i]是否在字符串P中//若不在说明T[i]无法与P中任一字符匹配令k=-1//这里使用字母表还可以做一个优化//就是判断T[i]是否出现在P[0..k]范围内不在则令k=-1if(IsInString(P,T[i])==false)k=-1;elsek=next[k];}}delete[]next;if(k>=(int)strlen(P))returni-(int)strlen(P);elsereturn-1;}13、考虑一个“模糊”的算法查找T的子串P,先快速找到与P相似的子串,再进一步确认之。

先得到P[0]P[n/2]P[n-1]三个字符,在T中找到T[i]=P[0]判断T[i+n-1]是否与P[n-1]相等再判断T[i+n/2]是否与P[n/2]相等,都相等则进一步判确认。

//没写14、设计一个算法确定K个矩阵相乘的最优次序,并分析该算法的时间复杂性。

老师的方法,动态规划,有点麻烦就不写了。

15、设计一个算法从数A[1:

n]中同时找出最大元素和最小元素,只需要不超过1.5n-2次比较。

将数组中的数两个一组做比较,较大的数放入一个数组,较小的数放入另一个数组,这样就把原数组分成两个子数组,一个数组中含最大元,另一个数组中含有最小元,各有n/2个元素。

再处理含最大元的子数组,将其中的数两个一组做比较,保留较大的数,直到只剩下一个数,即为最大元。

以同样方法处理含最小元的子数组。

//没写16、用分治法一个算法从数A[1:

n]中同时找出最大元素,分析算法的时间复杂性,并思考为什么是这样的结果。

不知道题目什么意思17、在一个数组中出现次数最多的元素称为“众数”,编写一个找出众数的算法,并分析算法时间复杂性。

先排序,然后遍历一遍寻找最长的相同元素序列。

算法默认出现2次及2次以上才为众数。

快排时间复杂度为O(nlogn),遍历一遍复杂度为O(n),故算法总时间复杂度为O(nlogn)//返回-1则未找到众数intnumber(Array,Len){//快排

QSort(Array,Len);max=1;num=-1;i=0;j=1while(imax){max=j-i;num=Array[i];}i=j;j=i+1}returnnum;}18、设计一个使用Hash法的算法在数组中找出“众数”,并分析时间复杂性。

Hash的方法很关键,不知道有什么简单的方法„„这里假设数组中数据范围为0~max,max为数组中最大元素,先找到max,确定了Hash的范围,再使用一对一Hash(directaddressing)。

时间复杂性为O(n)(查找最大元时间复杂度为O(n),遍历一遍数组为O(n),Hash的时间复杂度为O

(1),故算法时间复杂度为O(n),当然这里使用的方法受限制极强,不是通用的解答,时间复杂度也不可能有这么好,但是代码容易编写与理解)//Hash函数有点假hash(Brray,i){Brray[i]++;}//返回-1则未找到众数默认出现2次及2次以上才为众数intnumber(Array,Len){//找到最大数max=find_max(Array,Len);//新建一个数组Brray=newint[max+1];//初始化其中数据为0for(i=0;i

{hash(Brray,Array[i]);}//默认众数为-1出现次数为1次num=-1;nax=1;//在Brray中找最大数for(i=0;inax){nax=Brray[i];num=i;}}//删除Brray数组delete[]Brray;//返回找到的众数returnnum;}219、设计一个时间复杂性不超过O(n)的算法,找出n个数组成的序列中最长的单调递增序列。

比较简单,遍历一遍数组就可以了,这里为了写代码方便默认返回数组长度为1时,不存在递增序列,可以改成0更符合逻辑。

//Result为返回的序列开始指针RLen为序列长度increase(Array,Len,&Result,&RLen){RLen=1;//从Array[0]开始i记录起始位置j用于遍历数组i=0;j=1;while(j=Len)return;//递增序列一直后移到其末尾i=j-1;j++;while((jArray[j-1]))j++;//更新返回值if((j-i)>RLen){RLen=j-i;

Result=Array+i;}i=j;j++;}}20、从1,2,,n中找出所有质数,设计一个比较优的算法。

没有相当好的办法,谁知道效率又高又容易理解的麻烦告诉我一下//Result为返回的质数数组头指针RLen为数组长度increase(n,&Result,&RLen){//对n<5的情况优化if(n<1){RLen=0;return;}elseif(n==1){RLen=1;Result[0]=1;return;}elseif(n==2){RLen=2;Result[0]=1;Result[1]=2;return;}elseif(n<5){RLen=3;Result[0]=1;Result[1]=2;Result[2]=3;return;}RLen=3;Result[0]=1;Result[1]=2;

Result[2]=3;//新建一个辅助数组用于记录哪些数为非质数Array[n+1];//i为待判断的数for(i=5;i

=1){Result[RLen]=i;RLen++;}}}21、测试一个图是否连通图,可以用深度优先搜索算法或宽度优先搜索算法,在什么情况下,用哪种算法更好一些?

22、试求图中所有点对之间的所有路径,并找出两点之间最短的路径。

23、二叉检索树的主要问题是树高,编写一个控制检索树树高的算法。

24、试写一个在2—3树上删除一个节点的算法。

来段英文Thedeletionofaleaffroma2-3treeisperformedanalogously.Firsttheleafislocatedandremoved.Callptheparentoftheremovedleaf.Ifthenumberofchildrenofphasdecreasedfromthreetotwo,thetreeisstill2-3.Ifthenumberofchildrenofphasdecreasedfromtwotoone,mergepwithoneofitssiblings,possiblyreducingthenumberofchildrenofp'sparent.Proceedrecursively,uptotherootofthetree.Ifattheendtheroothasdegreeone,removeitandmakeitschildbecomeroot.代码有点长,老师上课讲过增加一个节点,原理有相似的地方//首先需要找到待删除的叶子节点nodesearch(root,a)

{//L()和M()用来取当前节点的左子节点的最大值与中间子节点的最大值//根结点为空返回空if(root==NULL)returnNULL;//左子节点为空则为叶子节点判断是否找到aif(root->left==NULL){if(root->value==a)returnroot;elsereturnNULL;}//L()和M()用来取当前节点的左子节点的最大值与中间子节点的最大值//小于等于L(root)则在其左子树中继续查找if(a<=L(root))returnsearch(root->left,a);//小于等于M(root)则在其中子树中继续查找if(a<=M(root))returnsearch(root->mid,a);//大于M(root)则在其右子树中继续查找returnsearch(root->right,a);}//删除节点首先调用search函数找到其父节点node=search(root,a);del(node){parent=node->parent;//若父节点有三个子节点直接删除nodeif(parent->right!

=NULL){//调整父节点的指针和信息if(parent->left==node){parent->left=parent->mid;parent->mid=parent->right;L(parent)=M(parent);M(parent)=parent->right->value;}elseif(parent->mid==node){parent->mid=parent->right;M(parent)=parent->right->value;}parent->right=NULL;//删除节点deletenode;}//不存在第三个子节点else

{//如果父节点是根节点选择其兄弟节点作为新的根节点if(parent==root){if(parent->left==node){root=parent->right;}elseroot=parent->left;//删除节点deletenode;return;}//父节点不是根节点则调用del函数删除父节点并将兄弟节点重新加入树中此处未定义add函数//临时保存兄弟节点的值if(parent->left==node){temp=parent->right->value;}elsetemp=parent->left->value;//删除节点deletenode;//删除父节点del(parent);//重新加入兄弟节点add(root,

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

当前位置:首页 > 经管营销 > 销售营销

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

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