1、第 1 页 共 41 页算法设计与分析(第 2 版)-王红梅- 胡明-习题答案习题 11. 图论诞生于七桥问题。出生于瑞士的伟大数学家欧拉(Leonhard Euler,17071783)提出并解决了该问题。七桥问题是这样描述的:一个人是否能在一次步行中穿越哥尼斯堡(现在叫加里宁格勒,在波罗的海南岸)城中全部的七座桥后回到起点,且每座桥只经过一次,图 1.7 是这条河以及河上的两个岛和七座桥的草图。请将该问题的数据模型抽象出来,并判断此问题是否有解。七桥问题属于一笔画问题。输入:一个起点输出:相同的点1, 一次步行2, 经过七座桥,且每次只经历过一次3, 回到起点该问题无解:能一笔画的图形只有
2、两类:一类是所有的点都是偶点。另一类是只有二个奇点的图形。2在欧几里德提出的欧几里德算法中(即最初的欧几里德算法)用的不是除法而是减法。请用伪代码描述这个版本的欧几里德算法1.r=m-n2.循环直到 r=02.1 m=n2.2 n=r2.3 r=m-n3 输出 m 3设计算法求数组中相差最小的两个元素(称为最接近数)的差。要求分别给出伪代码和 C+描述。/采用分治法/对数组先进行快速排序/在依次比较相邻的差图 1.7 七桥问题北区东区岛区南区第 2 页 共 41 页#include using namespace std;int partions(int b,int low,int high)
3、int prvotkey=blow;b0=blow;while (low=prvotkey)-high;blow=bhigh;while (lowusing namespace std;int main()int a=1,2,3,6,4,9,0;int mid_value=0;/将“既不是最大也不是最小的元素”的值赋值给它for(int i=0;i!=4;+i)if(ai+1aicoutusing namespace std;int main()double value=0;for(int n=1;nusing namespace std;int main ()double a,b;doubl
4、e arctan(double x);/声明a = 16.0*arctan(1/5.0);b = 4.0*arctan(1/239);cout 1e-15)/定义精度范围 f = e/i;/f 是每次 r 需要叠加的方程r = (i%4=1)?r+f:r-f; e = e*sqr;/e 每次乘于 x 的平方 i+=2;/i 每次加 2 /whilereturn r;7. 圣经上说:神 6 天创造天地万有,第 7 日安歇。为什么是 6 天呢?任何一个自然数的因数中都有 1 和它本身,所有小于它本身的因数称为这个数的真因数,如果一个自然数的真因数之和等于它本身,这个自然数称为完美数。例如,6=1+
5、2+3,因此 6 是完美数。神6 天创造世界,暗示着该创造是完美的。设计算法,判断给定的自然数是否是完美数#includeusing namespace std;int main()int value, k=1;cinvalue;for (int i = 2;i!=value;+i)while (value % i = 0 ) k+=i;/k 为该自然数所有因子之和value = value/ i;/forif(k=value)cout1)return 3*T(n-1);(2)int T(int n) if(n=1)return 1;else if(n1)return 2*T(n/3)+n;(
6、1 ) for (i = 1; i using namespace std;int main()long double result=1;double j=1;for(int i=1;iusing namespace std;int BF(char S, char T)int index = 0; int i = 0, j = 0; while (Si != 0) j+; else +index; i = index; j = 0; if (Tj = 0) return index + 1; else 第 10 页 共 41 页return 0;int main()char s119=“aba
7、bcabccabccacbab“;char s27=“abccac“;coutusing namespace std;void GetNext(char T , int next ) /求模式 T 的 next 值int i, j, len;next0 = -1;for (j = 1; Tj!=0; j+) /依次求 nextjfor (len = j - 1; len = 1; len-) /相等子串的最大长度为 j-1for (i = 0; i using namespace std;int main()int n;/分子int m;/分母int factor;/最大公因子int fact
8、or1;coutnm;int r = m % n;/因为是真分数 所以分母一定大于分子factor1=m;factor=n;while (r != 0) 第 12 页 共 41 页factor1 =factor;factor = r;r = factor1% factor;coutusing namespace std;int main()int a9=5,6,2,8,4,3,7,4,8;int result=0; /result 为题目要求的各位之和for(int i=0;i!=9;+i)if(i%2=0)result+=ai; /i 为偶数位时,结果加上其对应数组数的本身else resu
9、lt+=ai*10; /i 为奇数位时,结果加上对应数组数的 10 倍if(result%11=0)coutusing namespace std;int square(int x)return x*x;/用递归思想int resultmod(int a, int n)if(n= 0)return 1;if(n%2 = 0)return square(resultmod(a, n/2);/n 为偶数的时,取 n 的一半防止溢出else return a*resultmod(a, n-1);/n 为奇数时,取 n-1;int main()int a, n, m;coutanm;coutusing
10、 namespace std;void deletere(int a,int N)int b100=0;int i,k;k=0;static int j=0;for(i=0;iusing namespace std;int main()int a=1,2,1,5,3,2,9,4,5,5,3,5;int i,j;for( i=0;iusing namespace std;int partions(int l,int low,int high)int prvotkey=llow;l0=llow;while (low=prvotkey)-high;llow=lhigh;while (low usin
11、g namespace std; const int N = 20; void swap_ab ( int *p , int *q ) int tmp = *p; *p = *q; *q = tmp; void process ( int a, int n ) int *p, *q; p = q = a; while ( p != a+n-1 ) /p 向前遍历,直到便利完毕 if ( *(p+1) using namespace std;int main()int x,y,x0,y0;int summax=0,temp=0;for(x0=0;x0=summax)summax=temp;x=x
12、0;/符合 sum 最大值的 x第 19 页 共 41 页y=y0;/符合 sum 最大值得 y/forcout0 的元素进行判断1.1 循环变量 i 从 1n 重复进行下述操作:1.1.1 计算矩阵 i 次方,如果矩阵对角线上有0 的元素,则跳转到 1.21.1.2 否则+i;1.2 如果矩阵对角线有0 的元素,则输出该回路2 输出无解信息;13 找词游戏。要求游戏者从一张填满字符的正方形表中,找出包含在一个给定集合中的所有单词。这些词在正方形表中可以横着读、竖着读、或者斜着读。为这个游戏设计一个蛮力算法14. 变位词。给定两个单词,判断这两个单词是否是变位词。如果两个单词的字母完全相同,只
13、是位置有所不同,则这两个单词称为变位词。例如,eat 和 tea 是变位词。/判断 qwer 和 rewq 是否是变位词#include#includeusing namespace std;int main()char s5=“qwer“;char t5=“rewq“;for(int i=0;i!=4;+i)if(si!=t3-i)第 20 页 共 41 页coutusing namespace std;extern const int n=6;/声明int main()int an=0,6,1,2,3,5;/初始化第 22 页 共 41 页int mid=n;int num_max1=0,
14、num_max2=0;for(int i=0;inum_max1)num_max1=ai;for(int j=n+1;jnum_max2)num_max2=aj;if(num_max1=num_max2)coutusing namespace std;void LeftReverse(char *a, int begin, int end)for(int i=0;iusing namespace std;int data100;/在 m 个数中输出 n 个排列数( nusing namespace std;void Findnum(int *a,int n)int low=0;int high
15、=n-1;while(lowmid)第 25 页 共 41 页high=mid-1;elselow=mid+1;int main()int a7=1,0,2,5,6,7,9;Findnum(a,7);return 0;时间复杂度为 O(log2n)。10. 在一个序列中出现次数最多的元素称为众数。请设计算法寻找众数并分析算法的时间复杂性。/先对序列进行快速排序/再进行一次遍历/输出众数的重复次数#include using namespace std;int partions(int b,int low,int high)int prvotkey=blow;b0=blow;while (low
16、=prvotkey)-high;blow=bhigh;while (lowmax) max=count;count=0;第 27 页 共 41 页/whilecoutusing namespace std;const int n=8;void partions(int a,int low,int high)/进行一趟快排int prvotkey=alow;a0=alow;while (low=prvotkey) +low;ahigh=alow;alow=prvotkey;第 28 页 共 41 页/如果 s1(大的数集)的的个数大于 n/2if(low=n/2)for(int i=0;iak-
17、1)int temp1=ak;ak=ak-1;ak-1=temp1;/forint main()int an=1,3,5,9,6,0,-11,-8;partions(a,0,n-1);for(int i=0;iaj,则序偶(a i, aj)称为该排列的一个逆序。例如,2, 3, 1 有两个逆序:(3, 1)和(2, 1)。设计算法统计给定排列中含有逆序的个数。/用归并进行排序/当一个子集的一个数大于第二个子集的一个数,为逆序,即 aiaj/则逆序数为 end-j+1;#includeusing namespace std;int count;void Merge(int a,int a1,int begin,int mid,int end)/合并子序列int i=begin,j=mid+1,k=end;while(iusing namespace std;int n;char a100;