算法分析及设计及案例习题解析
(整理版)几种常见的算法案例分析

几种常见的算法案例分析算法不仅是数学及其应用的重要的组成局部,也是计算机科学的重要根底,其中算法的重要思想在几种常见的算法例案中得以较好的表达。
本文从几种常见算法案例出发,来探究一下算法的内涵。
一、辗转相除法所谓辗转相除法,就是对于给定的两个数,用较大的数除以较小的数,假设余数不为零,那么将余数和较小的数构成新的一对数,继续上面的除法,直到大数被小数除尽,那么这时的较小的数就是原来两个数的最大公约数。
例1. 写出求两个正数,()a b a b >的最大公约数的一个算法。
算法设计:第一步:输入两个正整数,()a b a b >;第二步:把a b ÷的余数赋予r ;第三步:如果0r ≠,那么把b 赋予a ,把r 赋予b ,转到第二步;否那么转到第四步;第四步:输入最大公约数b 。
程序框图下列图所示:用伪代码表示:input “a=,b=〞;a,bdo r=mod(a,b)a=bb=rloop until r=0print bend二、更相减损术所谓更相减术,就是对于给定的两个数,以其中较大的数减去较小的数,然后将差和较小的数构成一对新数,再用较大的数减去较小的数,反复执行此步骤,直到差数和较小的数相等,此时相等的两个数就是原两个数的最大公约数。
在我国古代的<<九章算术>>中有这样的描述“约分术曰:可半者半之,不可半者会置分母分子之数,以少减多,更相损减,求其等也,以等数约之。
〞意思是说如果分母、分子都是偶数,那么先除以2;如果不全是偶数,便将分子与分母互减,以少减多,直到得出最大公约数为止,用最大公约数约分子与分母,便可使分数最简。
如果两个数都是偶数,也不除以2,直接求最大公约数。
这是一种多么奇妙的方法啊,我们古代人在许多方面都比西方先进,这是值得我们自豪的。
以上题为例,算法可以这样来设计:第一步:输入两个正整数,()a b a b >;第二步:假设a 不等于b ,那么执行第三步;否那么执行第五步;第三步:把a b -的差赋予r ;第四步:如果b r >,那么把b 的值赋予a ,否那么把r 的值赋予a ,执行第二步; 第五步:输出最大公约数b 。
算法设计与分析习题答案

算法设计与分析习题答案算法设计与分析是计算机科学中一个重要的领域,它涉及到算法的创建、优化以及评估。
以下是一些典型的算法设计与分析习题及其答案。
习题1:二分查找算法问题描述:给定一个已排序的整数数组,编写一个函数来查找一个目标值是否存在于数组中。
答案:二分查找算法的基本思想是将数组分成两半,比较中间元素与目标值的大小,如果目标值等于中间元素,则查找成功;如果目标值小于中间元素,则在左半部分继续查找;如果目标值大于中间元素,则在右半部分继续查找。
这个过程会不断重复,直到找到目标值或搜索范围为空。
```pythondef binary_search(arr, target):low, high = 0, len(arr) - 1while low <= high:mid = (low + high) // 2if arr[mid] == target:return Trueelif arr[mid] < target:low = mid + 1else:high = mid - 1return False```习题2:归并排序算法问题描述:给定一个无序数组,使用归并排序算法对其进行排序。
答案:归并排序是一种分治算法,它将数组分成两半,分别对这两半进行排序,然后将排序好的两半合并成一个有序数组。
```pythondef merge_sort(arr):if len(arr) > 1:mid = len(arr) // 2left_half = arr[:mid]right_half = arr[mid:]merge_sort(left_half)merge_sort(right_half)i = j = k = 0while i < len(left_half) and j < len(right_half): if left_half[i] < right_half[j]:arr[k] = left_half[i]i += 1else:arr[k] = right_half[j]j += 1k += 1while i < len(left_half):arr[k] = left_half[i]i += 1k += 1while j < len(right_half):arr[k] = right_half[j]j += 1k += 1arr = [38, 27, 43, 3, 9, 82, 10]merge_sort(arr)print("Sorted array is:", arr)```习题3:动态规划求解最长公共子序列问题问题描述:给定两个序列,找到它们的最长公共子序列。
北大屈婉玲算法分析与设计 习题解答2

101i 的个数仓储问题作业二1.x i =0,1是货柜i 的个数,仓储问题:max nx l 1∑∑=n ii i 令C [k ,y ]是只允许装前k 个货柜,库房长度为y 时的最大收益1,0,1=≤=i i i ix L x l 1],1[],[k L l y y k C y k C k ⎨⎧>−−−<−=1],1[}],1[],,1[max{l y C l y l l y k C y k C kk k =⎩≥≥+1伪码略.W (n )=O (nD )33. 作业调度与01背包问题类似使用动态规划方法0-1背包问题类似,使用动态规划方法. 令N j (d )表示对作业集{1,2,…,j },结束时间为d 的最优调度的效益那么效益,那么)(}))((),(max{)(11≥+−=−−j t d v j t d N d N d N j j j j 1)()()(1⎧≤<=−dt v j t d d N d N j j 0)1(0)()(11>⎩⎨>=d d t d N 自底向上计算,存储使用备忘录。
可以使用标记函数B (j )记录使得N j (d )达到最大是否N j (d )=N j −1(d ). 如果不等,B (j )=1,0.3否则为0.时间W (n )=O (nD )输入:加工时间伪码Job(t ,v ,D )t [1..n ],效益v [1..n ],结束时间D 输出:最优效益N [n,D ],标记函数B ,解是{k | B [k ]=1}1.for 1to −1. for d ←1 to t [1]12. N [1,d ]←0, B [1] ←03. for d ←t [1] to D4. N [1,d ]←v [1], B [1]←15. for k ←2 to n6for 1to 6. for d ←1 to D7. N [k ,d ]←N [k −1,d ]8.8. B [k ]←09. if d ≥t [k ] and N [k −1,d −t [k ]]+v [k ]>N [k −1,d ]10. then N [k ,d ]←N [k −1,d −t [k ]]+v [k ]411. B [k ]←14014. 双约束0-1背包问题种物品背包重量限制为m [i ,j ,k ]表示使用前i 种物品,背包重量限制为j ,容积为k 时的最大价值+−−−−=}],,1[],,,1[max{],,[v c k w j i m k j i m k j i m i i i <<−=≥≥or ],,1[],,[and c k w k i m k i m c k w j i i⎨⎧≥≥=111and ],,1[c k w j v k j m j j j i i ⎩<<11or 0c k w j 5W (n )= O (nWV )55.合并数组问题0n-1i j k k+110i jn -16递推公式X {合并问题含有整数个数⎧={x 0,x 1,…, x n -1},X ij 表示{x i ,…,x j }合并问题,含有整数个数是n ij ,完成这些合并所需要最少的比较次数记作m [i ,j ]⎪⎪<+++∑=<≤j i a j k m k i m j i l l j k i ]},1[],[{max ⎪⎪⎨>++++=∑∑=−=−≤≤j i a a j n k m k i m j i m j l n l n k i 11]},mod )1[(],[{max ],[⎩<≤l i l jk 00m [i,i ]= 0i=0,2,…,n -1]}mod )1(,[{max 10n n i i m m n i −+=−≤≤7T (n )=O (n 3)标记函数s [i ,j ]记录使m [i ,j ] 取得最小值的k。
算法设计和分析习题答案解析1_6章

习题11. 图论诞生于七桥问题。
出生于瑞士的伟大数学家欧拉(Leonhard Euler ,1707—1783)提出并解决了该问题。
七桥问题是这样描述的:一个人是否能在一次步行中穿越哥尼斯堡(现在叫加里宁格勒,在波罗的海南岸)城中全部的七座桥后回到起点,且每座桥只经过一次,图1.7是这条河以及河上的两个岛和七座桥的草图。
请将该问题的数据模型抽象出来,并判断此问题是否有解。
七桥问题属于一笔画问题。
输入:一个起点输出:相同的点1, 一次步行2, 经过七座桥,且每次只经历过一次3, 回到起点该问题无解:能一笔画的图形只有两类:一类是所有的点都是偶点。
另一类是只有二个奇点的图形。
2.在欧几里德提出的欧几里德算法中(即最初的欧几里德算法)用的不是除法而是减法。
请用伪代码描述这个版本的欧几里德算法1.r=m-n2.循环直到r=02.1 m=n2.2 n=r2.3 r=m-n3 输出m3.设计算法求数组中相差最小的两个元素(称为最接近数)的差。
要求分别给出伪代码和C++描述。
//采用分治法//对数组先进行快速排序//在依次比较相邻的差#include <iostream>using namespace std;int partions(int b[],int low,int high) {图1.7 七桥问题int prvotkey=b[low];b[0]=b[low];while (low<high){while (low<high&&b[high]>=prvotkey)--high;b[low]=b[high];while (low<high&&b[low]<=prvotkey)++low;b[high]=b[low];}b[low]=b[0];return low;}void qsort(int l[],int low,int high){int prvotloc;if(low<high){prvotloc=partions(l,low,high); //将第一次排序的结果作为枢轴 qsort(l,low,prvotloc-1); //递归调用排序由low 到prvotloc-1qsort(l,prvotloc+1,high); //递归调用排序由 prvotloc+1到 high}}void quicksort(int l[],int n){qsort(l,1,n); //第一个作为枢轴,从第一个排到第n个}int main(){int a[11]={0,2,32,43,23,45,36,57,14,27,39};int value=0;//将最小差的值赋值给valuefor (int b=1;b<11;b++)cout<<a[b]<<' ';cout<<endl;quicksort(a,11);for(int i=0;i!=9;++i){if( (a[i+1]-a[i])<=(a[i+2]-a[i+1]) )value=a[i+1]-a[i];elsevalue=a[i+2]-a[i+1];}cout<<value<<endl;return 0;}4.设数组a[n]中的元素均不相等,设计算法找出a[n]中一个既不是最大也不是最小的元素,并说明最坏情况下的比较次数。
OpenJudge算法设计与分析习题解答

1、硬币面值组合描述使用1角、2角、5角硬币组成n 角钱。
设1角、2角、5角的硬币各用了a、b、c个,列出所有可能的a, b, c组合。
输出顺序为:先按c的值从小到大,若c相同则按b的值从小到大。
输入一个整数n(1 <= n <= 100),代表需要组成的钱的角数。
输出输出有若干行,每行的形式为:i a b c第1列i代表当前行数(行数从001开始,固定3个字符宽度,宽度不足3的用0填充),后面3列a, b, c分别代表1角、2角、5角硬币的个数(每个数字固定12个字符宽度,宽度不足的在左边填充空格)。
样例输入样例输出源代码:#include<stdio.h>#include<stdlib.h>int main(){int t=1;int i,j,k;int n;scanf("%d",&n);int A=n,B=n/2,C=n/5;for(i=0;i<=C;i++){for(j=0;j<=B;j++){for(k=0;k<=A;k++){if(i*5+j*2+k*1==n){printf("%03d%12d%12d%12d\n",t,k,j,i);t++;}}}}getchar();return 0;}2、比赛排名描述5名运动员参加100米赛跑,各自对比赛结果进行了预测:A说:E是第1名。
B说:我是第2名。
C说:A肯定垫底。
D说:C肯定拿不了第1名。
E说:D应该是第1名。
比赛结束后发现,只有获第1名和第2名的选手猜对了,E不是第2名和第3名,没有出现名次并列的情况。
请编程判断5位选手各是第几名。
输入无输出输出要求:按ABCDE的顺序输出5行,其中第1行是A的名次,第2行是B的名次,第3行是C的名次,第4行是D的名次,第5行是E的名次。
样例输入样例输出源代码:#include<stdio.h>int main(){printf("5\n");printf("2\n");printf("1\n");printf("3\n");printf("4\n");return 0;}3、鸡兔同笼描述一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。
算法设计与分析试题及答案

1. 按分治策略求解棋盘覆盖问题时,对于如图所示的24×24的特殊棋盘,共需要多少个L 型骨牌;并在棋盘上填写L 型骨牌的覆盖情况。
2. 假设有7个物品,给出重量和价值。
若这些物品均不能被分割,且背包容量M =140,使用回溯方法求解此0-1背包问题。
请画出状态空间搜索树。
3. 假设有7个物品,它们的重量和价值如下表所示。
若这些物品均可以被分割,且背包容量M=140,使用贪心算法求解此背包问题。
请写出求解策略和求解过程。
W (35,30,50,60,40,10,25)p (10,40,30,50,35,40,30)4. 在给出的电路板中,阴影部分是已作了封锁标记的方格,请按照队列式分支限界法在图中确定a 到b 的最短布线方案,要求布线时只能沿直线或直角进行,在图中标出求得最优解时各方格情况。
5. 画出字符表的哈夫曼编码对应的二叉树。
6. 已知1()*()i i k k ij r r A a +=,k =1,2,3,4,5,6,r 1=5,r 2=10,r 3=3,r 4=8,r 5=5,r 6=20,r 7=6,求矩阵链积A 1×A 2×A 3×A 4×A 5×A 6的最佳求积顺序。
7. 给出城市网络图,售货员要从城市1出发,经过所有城市回到城市1,画出该问题的解空间树,描述出用优先队列式分支限界法求解时的搜索情况。
表示出优先队列、当前扩展结点等的变化情况。
8. 依据优先队列式分支限界法,求从s 点到t 点的单源最短路径,画出求得最优解的解空间树。
一、假设有7个物品,它们的重量和价值如下表所示。
若这些物品均不能被分割,且背包容量M=150,使用回溯方法求解此背包问题。
请写出状态空间搜索树(20分)。
答:按照单位效益从大到小依次排列这7个物品为:FBGDECA 。
将它们的序号分别记为1~7。
则可生产如下的状态空间搜索树。
其中各个节点处的限界函数值通过如下方式求得:【排序1分】5x =6x =7x =17分,每个节点1分】a .1501154040305035190.62540-++++⨯=7(1,1,1,1,,0,0)8b. 1501154040305030177.560-++++⨯=7(1,1,1,1,0,,0)12c .4040305010170++++=(1,1,1,1,0,0,1)d. 1501054040303530167.560-++++⨯=3(1,1,1,0,1,,0)4e. 150130404050353017560-++++⨯=1(1,1,0,1,1,,0)3f. 1501304040503510170.7135-++++⨯=4(1,1,0,1,1,0,)7g. 40405030160+++=(1,1,0,1,0,1,0)h. 1501404040353010146.8535-++++⨯=2(1,1,0,0,1,1,)7i.1501254030503530167.560-++++⨯=5(1,0,1,1,1,,0)12 j. 1501454030503530157.560-++++⨯=1(0,1,1,1,1,,0)12在Q 1处获得该问题的最优解为(1,1,1,1,0,0,1),背包效益为170。
算法设计与分析的一些实例分析

实验一递归与分治策略一、实验目的:熟练掌握递归与分治策略的思想并应用其解决实际问题。
二、递归与分治策略思想基本思想:将要求解的较大规模的问题分割成k个更小规模的子问题。
对这k个子问题分别求解。
如果子问题的规模仍然不够小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。
实验题目(1-2):找出从自然数1,2,…,n中任取r个数的所有组合。
算法思想:当组合的第一个数字选定时,其后的数字是从余下的m-1个数中取k-1数的组合。
这就将求m个数中取k个数的组合问题转化成求m-1个数中取k-1个数的组合问题。
设函数引入工作数组a[ ]存放求出的组合,约定函数将确定的k个数字组合的第一个数字放在a[k]中,当一个组合求出后,才将a[ ]中的一个组合输出。
第一个数可以是m、m-1、……、k,函数将确定组合的第一个数字放入数组后,有两种可能的选择,因还未确定组合的其余元素,继续递归去确定;或已确定了组合的全部元素,输出这个组合。
问题描述:找出从自然数1、2、……、n中任取r个数的所有组合。
例如n=5,r=3的所有组合为:(1)5、4、3 (2)5、4、2 (3)5、4、1(4)5、3、2 (5)5、3、1 (6)5、2、1(7)4、3、2 (8)4、3、1 (9)4、2、1(10)3、2、1分析所列的10个组合,可以采用这样的递归思想来考虑求组合函数的算法。
设函数为void find(int m,int k)为找出从自然数1、2、……、m中任取k个数的所有组合。
当组合的第一个数字选定时,其后的数字是从余下的m-1个数中取k-1数的组合。
这就将求m个数中取k 个数的组合问题转化成求m-1个数中取k-1个数的组合问题。
设函数引入工作数组a[ ]存放求出的组合的数字,约定函数将确定的k个数字组合的第一个数字放在a[k]中,当一个组合求出后,才将a[ ]中的一个组合输出。
第一个数可以是m、m-1、……、k,函数将确定组合的第一个数字放入数组后,有两种可能的选择,因还未去顶组合的其余元素,继续递归去确定;或因已确定了组合的全部元素,输出这个组合。
算法分析若干实例问题解析

最小长度电路板排列问题问题描述小长度电路板排列问题是大规模电子系统设计中提出的实际问题。
该问题的提法是: 将n块电路板以最佳排列方案插入带有n个插槽的机箱中。
n块电路板的不同的排列方式对应于不同的电路板插入方案。
设B={1,2,…,n }是n块电路板的集合。
集合L={ N1 ,N2 ,…,Nm }是n块电路板的m个连接块。
其中每个连接块Ni 是B的一个子集,且Ni 中的电路板用同一根导线连接在一起。
连接块的长度是指该连接块中第1 块电路板到最后1 块电路板之间的距离。
试设计一个分支限界法找出所给n个电路板的最佳排列,使得m个连接块中最大长度达到最小。
例:如图,设n=8, m=5,给定n块电路板及其m个连接块:B={1, 2, 3, 4, 5, 6, 7, 8},N1={4, 5, 6},N2={2, 3},N3={1, 3},N4={3, 6},N5={7, 8};这8块电路板两个可能的排列如图所示:在最小长度电路板排列问题中,连接块的长度是指该连接块中第1 块电路板到最后1 块电路板之间的距离。
例如在左图示的电路板排列中,连接块N4的第1 块电路板在插槽3 中,它的最后1块电路板在插槽6中,因此N4的长度为3。
同理N2的长度为2。
图中连接块最大长度为3。
试设计一个分支限界法找出所给n个电路板的最佳排列,使得m个连接块中最大长度达到最小。
输入数据:第一行有2 个正整数n和m。
接下来的n 行中,每行有m个数。
第k行的第j个数为0 表示电路板k不在连接块j 中,1 表示电路板k在连接块j中。
输出数据为计算出的电路板排列最小长度与相应的排列方式。
Sample Input8 51 1 1 1 10 1 0 1 00 1 1 1 01 0 1 1 01 0 1 0 01 1 0 1 00 0 0 0 10 1 0 0 1Sample Output45 4 3 16 2 8 7可用策略电路板排列问题是NP难问题,因此不大可能找到解此问题的多项式时间算法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
习题解析第1章1. 解析:算法主要是指求解问题的方法。
计算机中的算法是求解问题的方法在计算机上的实现。
2. 解析:算法的五大特征是确定性、有穷性、输入、输出和可行性。
3. 解析:计算的算法,其中n是正整数。
可以取循环变量i的值从1开始,算i的平方,取平方值最接近且小于或者等于n的i即可。
4. 解析:可以使用反证法,设i=gcd(m, n)=gcd(n, m mod n),则设m=a*i,n=b*i,且a与b互质,这时m mod n=(a-x*b)*i,只需要证明b和a-x*b互质,假设二者不互质,可以推出a与b不互质,因此可以得到证明。
5. 解析:自然语言描述:十进制整数转换为二进制整数采用“除2取余,逆序排列”法。
具体做法是:用2整除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,如此进行,直到商为0时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。
流程图:如图*.1图*.1 十进制整数转换成二进制整数流程图6. 解析:a.如果线性表是数组,则可以进行随机查找。
由于有序,因此可以进行折半查找,这样可以在最少的比较次数下完成查找。
b.如果线性表是链表,虽然有序,则只能进行顺序查找,从链表头部开始进行比较,当发现当前节点的值大于待查找元素值,则查找失败。
7. 解析:本题主要是举例让大家了解算法的精确性。
过程中不能有含糊不清或者二义性的步骤。
大家根据可行的方式总结一下阅读一本书的过程即可。
8. 解析:数据结构中介绍的字典是一种抽象数据结构,由一组键值对组成,各个键值对的键各不相同,程序可以将新的键值对添加到字典中,或者基于键进行查找、更新或删除等操作。
由于本题已知元素唯一,因此大家可以据此建立一个自己的字典结构。
实现字典的方法有很多种:•最简单的就是使用链表或数组,但是这种方式只适用于元素个数不多的情况下;•要兼顾高效和简单性,可以使用哈希表;•如果追求更为稳定的性能特征,并且希望高效地实现排序操作的话,则可以使用更为复杂的平衡树。
在字典之上的主要操作可以有:创建操作,添加操作,删除操作,查找操作,以及必要的字典维护操作。
第2章1. 解析:根据本章所述,递归算法和非递归算法的数学分析方法分为5个步骤。
2. 解析:本题相当于对多项式找“主项”,也就是在除去常系数外,影响函数值递增速度最快的项。
a) 22310()n n n θ+∈b) 22(2)10n n n θ+∈ c) 121()c nθ+∈,c 为常数 d) 32log (log )n n θ∈e) 10log 3()nn θ∈3. 解析:本题中如果手套分左右手,则最优情况选2只,最差情况选12只。
本题中如果手套不分左右手,则最优情况仍然选2只,最差情况选4只。
从本题的初衷推测设置题目应该是分左右手的手套,在考虑颜色的情况下,选择一双进行匹配。
4. 解析:本题的一般解法可以使用高等数学中求二者比值的极限来确定结果。
a) 相同 b) 第一个小 c) 二者相同 d) 第一个大 e) 二者相同 f) 第一个小 5. 解析:6. 解析:参见本章例2.7。
第3章1. 解析:蛮力法主要依靠问题的定义,采用简单直接的求解方法。
由此决定了蛮力法是解决问题的最简单也是最普遍的算法,同时其经常作为简单问题求解的方法和衡量其他算法的依据。
2. 解析:2,6,1,4,5,3,2选择排序:|2 6 1 4 5 3 2i=0: min最后得2,交换二者。
1 |62 4 53 2 i=1: min最后得2,交换二者。
1 2 |6 4 5 3 2i=2: min最后得6,交换二者。
1 2 2 |4 5 3 6 i=3: min最后得5,交换二者。
1 2 2 3 |5 4 6 i=4: min最后得5,交换二者1 2 2 3 4 |56i=5: min最后得5。
1 2 2 3 4 5 |6结束。
冒泡排序:2 6 1 4 53 22 1 4 53 2 |6 i=0: 最大值6就位。
1 2 4 3 2 |5 6 i=1:第二大值5就位。
1 2 3 2 |4 5 6 i=2:第三大值4就位。
1 2 2 |3 4 5 6 i=3:第四大值3就位。
1 2 |2 3 4 5 6 i=4:第五大值2就位。
1 |2 23456 i=5:第六大值2就位,剩余的1也就位,排序结束。
3. 解析:选择排序不稳定,如3.1.1节例子:4,4,2。
冒泡排序稳定。
4. 解析:如2题例子,到i=4时就没有发生交换的活动了。
这时可以在冒泡排序的交换部分加入一个布尔变量,如本次循环中没有发生交换,则以后的扫描就可以不进行。
5. 解析:如果n个点共线,则其最近对只需要考察相邻的点对,因此在对点进行按行坐标排序后,只需要两两计算相邻两点距离,就可以找到最近对。
6. 解析:所有的过程与寻找二维空间中的最近点对类似,只是计算距离的公式变为:sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z) 使用循环计算任意两个点之间的距离,然后记录最小值即可。
类似的,如果推广到n维空间,需要考虑空间中任意两点的距离计算公式,同样计算每两个点之间的距离,并记录最小距离即可。
7. 解析:a) 线段的凸包为本身,极点为两个端点。
b) 正方形的凸包为本身,极点为四个顶点。
c) 正方形的边界不是凸包,凸包为正方形(包括边界和部)。
d) 直线的凸包为本身,没有极点。
8. 解析:哈密顿回路的穷举查找算法,首选选择起点(图中任意一个点开始),之后不断寻找下一个点,下一个点应该满足:1) 不在已经走过的点中;2)与上一个点有直连路径。
如果这样能找到回到起点的路径,并且遍历所有点,则为一条哈密顿回路。
然后依次进行下一个可行点的选择。
9. 解析:生成给定元素的一个排列,通过连续比较它们之间的元素,检查它们是否符合排序的要求。
如果符合就停止,否则重新生成新的排列。
最差情况生成排列的个数是!n,每趟连续元素比较次数为n-1次。
所以效率类型为O n n 。
(!*(1))第4章1. 解析:假定把16枚硬币上网例子看作一个大的问题。
(1)把这一问题分成两个小问题,随机选择8个硬币作为第一组称为A组,剩下的8个硬币作为第二组称为B组;这样,就把16个硬币的问题分成两个8个银币的问题来解决;(2)判断A组和B组中是否有伪币,可以使用仪器比较A组硬币和B组硬币的重量;假如两组硬币重量相等,则可以判断伪币不存在;假如两组硬币重量不相等,则存在伪币,并且可以判断它位于较轻的那一组硬币中;(3)假设B是轻的那一组,因此再把它分成两组,每组有4个硬币,称其中一组为B1,另一组为B2,比较这两组,肯定有一组轻一些,假设B1轻,则伪币在B1中,再将B1分为两组,每组有两个硬币,称其中一组为B1a,另一组为B1b。
比较这两组,可以得到一个较轻的组,由于这个组织有两个硬币,因此不必再细分。
比较组中两个硬币的重量,可以立即知道哪个硬币轻一些,轻币就是要找的伪币;最终,比较次数为4次。
2. 解析:逆序对是指在序列{a0,a1,a2...a n}中,若a i<a j(i>j),则(a i,a j)上一对逆序对。
而逆序数是指序列中逆序对的个数。
例如:1 2 3是顺序,则逆序数是0;1 3 2中(2,3)满足逆序对的条件,所以逆序数只有1;3 2 1中(1,2)(1,3)(2,3)满足逆序对,所以逆序是3。
由定义不能想象,序列n的逆序数围在[0,n*(n-1)/2],其中顺序时逆序数为0,完全逆序时逆序数是n*(n-1)/2。
对于一个数组s将其分为2个部分s1和s2,求s1和s2的逆序对个数,再求s1和s2合并后逆序对的个数:这个过程与merge排序的过程是一样的,可以使用merge排序求得。
代码如下://a为字符数组,len为字符数组的长度int number = 0; //number表示逆序对的个数void copy(char *dest, char *src, int l, int r){while(l <= r){dest[l] = src[l]; l++;}void mergeSort(char *a, int size){char *b = (char*)malloc(sizeof(char) * size);mergePass(a, b, 0, size - 1);free(b);}void mergePass(char *a, char *b, int l, int r) {int m;if(l < r){m = (l + r) / 2;mergePass(a,b,l,m);mergePass(a,b,m+1,r);merge(a,b,l,m,r);copy(a,b,l,r);}}void merge(char *a, char *b, int l, int m, int r) {int i = l, j = m + 1;while( i <= m && j <= r){if(a[i] <= a[j]) b[l++] = a[i++];else{b[l++] = a[j++];number += m-i+1;}while(i <= m) b[l++] = a[i++];while(j <= r) b[l++] = a[j++];}3. 解析:当序列A[1..n]中的元素的个数n=2时,通过直接比较即可找出序列的第2大元素。
当n>2时,先求出序列A[1..n-1]中的第1大元素x1和第2大元素x2;然后,通过2次比较即可在三个元素x1,x2和A[n]中找出第2大元素,该元素即为A[1..n]中的第2大元素。
SecondElement (A[low..high], max1, max2){ //假设主程序中调用该过程条件为high-low>=2if(high-low==2){ if(A[low]<A[high]) { max2=A[low]; max1=A[high]; }else { max2=A[high]; max1=A[low]; }}else{ SecondElement (A[low .. high],x1,x2);if(x1<=A[n]) {max2=max1; max1=A[n];}elseif(x2>=A[n]) {max2=x2; max1=x1;}else {max2=A[n]; max1=x1;}}}该算法的时间复杂度满足如下递归方程:T(n)=T(n-1)+2; T(2)=1。