算法设计与分析习题答案1-6章

发布时间 : 星期日 文章算法设计与分析习题答案1-6章更新完毕开始阅读

O(N)+x=2*O(N/2)+2*x

a*O(N)+x=a*(2*O(N/2)+x)+x=2*a *O(N/2)+(a+1)*x 由此可知,时间复杂度可达到O(n);

3.分治策略一定导致递归吗如果是,请解释原因。如果不是,给出一个不包含递归的分治例子,并阐述这种分治和包含递归的分治的主要不同。

不一定导致递归。

如非递归的二叉树中序遍历。

这种分治方法与递归的二叉树中序遍历主要区别是:应用了栈这个数据结构。

4. 对于待排序序列(5, 3, 1, 9),分别画出归并排序和快速排序的递归运行轨迹。

归并排序:

第一趟:(5,3)(1,9); 第二趟:(3,5,1,9); 第三趟:(1,3,5,9);

快速排序:

第一趟:5( ,3,1,9);设计分治算法求一个数组中的最大元素,并分析时间性能。

设计分治算法,实现将数组A[n]中所有元素循环左移k个位置, 要求时间复杂性为O(n),空间复杂性为O(1)。例如,对abcdefgh循环左移3位得到defghabc。

设计递归算法生成n个元素的所有排列对象。

#include using namespace std;

int data[100];

设计分治算法求解一维空间上n个点的最近对问题。

参见最近对问题的算法分析及算法实现

9. 在有序序列(r1, r2, …, rn)中,存在序号i(1≤i≤n),使得ri=i。请设计一个分治算法找到这个元素,要求算法在最坏情况下的时间性能为O(log2n)。

在一个序列中出现次数最多的元素称为众数。请设计算法寻找众数并分析算法的时间复杂性。

设M是一个n×n的整数矩阵,其中每一行(从左到右)和每一列(从上到下)的元素都按升序排列。设计分治算法确定一个给定的整数x是否在M中,并分析算法的时间复杂性。

12. 设S是n(n为偶数)个不等的正整数的集合,要求将集合S划分为子集S1和S2,使得| S1|=| S2|=n/2,且两个子集元素之和的差达到最大。

设a1, a2,…, an是集合{1, 2, …, n}的一个排列,如果iaj,则序偶(ai, aj)称为该排列的一个逆序。例如,2, 3, 1有两个逆序:(3, 1)和(2, 1)。设计算法统计给定排列中含有逆序的个数。

k循环赛日程安排问题。设有n=2个选手要进行网球循环赛,要求设计一个满足以下要求的比赛日程表:

(1)每个选手必须与其他n-1个选手各赛一次; (2)每个选手一天只能赛一次。

采用分治方法。

将2^k选手分为2^k-1两组,采用递归方法,继续进行分组,直到只剩下2个选手时,然后进行比赛,回溯就可以指定比赛日程表了

n15. 格雷码是一个长度为2的序列,序列中无相同元素,且每个元素都是长度为n的

3

二进制位串,相邻元素恰好只有1位不同。例如长度为2的格雷码为(000, 001, 011, 010, 110, 111, 101, 100)。设计分治算法对任意的n值构造相应的格雷码。

矩阵乘法。两个n×n的矩阵X和Y的乘积得到另外一个n×n的矩阵Z,且Zij

满足 (1≤i, j≤n),这个公式给出了运行时间为O(n)的算法。可以用分 治法解决矩阵乘法问题,将矩阵X和Y都划分成四个n/2×n/2的子块,从而X和Y的乘积可以用这些子块进行表达,即

3

从而得到分治算法:先递归地计算8个规模为n/2的矩阵乘积AE、BG、AF、BH、CE、DG、CF、DH,然后再花费O(n2)的时间完成加法运算即可。请设计分治算法实现矩阵乘法,并分析时间性能。能否再改进这个分治算法

习题5

1. 下面这个折半查找算法正确吗如果正确,请给出算法的正确性证明,如果不正确,请说

明产生错误的原因。

int BinSearch(int r[ ], int n, int k) {

int low = 0, high = n - 1; int mid;

while (low <= high) {

mid = (low + high) / 2; if (k < r[mid]) high = mid;

else if (k > r[mid]) low = mid;

else return mid; }

return 0; }

错误。 正确算法:

int BinSearch1(int r[ ], int n, int k) {

int low = 0, high = n - 1; int mid;

while (low <= high) {

mid = (low + high) / 2; if (k < r[mid]) high = mid - 1;

else if (k > r[mid]) low = mid + 1;

else return mid; }

return 0; }

2. 请写出折半查找的递归算法,并分析时间性能。

求两个正整数m和n的最小公倍数。(提示:m和n的最小公倍数lcm(m, n)与m和n的最大公约数gcd(m, n)之间有如下关系:lcm(m, n)=m×n/gcd(m, n))

插入法调整堆。已知(k1, k2, …, kn)是堆,设计算法将(k1, k2, …, kn, kn+1)调整为堆(假设调整为大根堆)。

参照:

void SiftHeap(int r[ ], int k, int n) {

int i, j, temp;

i = k; j = 2 * i + 1; 设计算法实现在大根堆中删除一个元素,要求算法的时间复杂性为O(log2n)。

计算两个正整数n和m的乘积有一个很有名的算法称

n m 为俄式乘法,其思想是利用了一个规模是n的解和一个规50 65 25 130 130 模是n/2的解之间的关系:n×m=n/2×2m(当n是偶数)

12 260 或:n×m=(n-1)/2×2m+m(当n是奇数),并以1×m=m6 520 作为算法结束的条件。例如,图给出了利用俄式乘法计算3 1040 1040 1 2080 2080 + 50×65的例子。据说十九世纪的俄国农夫使用该算法并因

3250 此得名,这个算法也使得乘法的硬件实现速度非常快,因

图 俄式乘法 为只使用移位就可以完成二进制数的折半和加倍。请设计算法实现俄式乘法。

拿子游戏。考虑下面这个游戏:桌子上有一堆火柴,游戏开始时共有n根火柴,两个玩家轮流拿走1,2,3或4根火柴,拿走最后一根火柴的玩家为获胜方。请为先走的玩家设计一个制胜的策略(如果该策略存在)。

如果桌上有小于4根的火柴,先手必胜,如果是5根,先手必输;依次类推,同理15、20、25…….都是必输状态;所有每次把对手逼到15、20、25…….等必输状态,就可以获胜。

9. 竞赛树是一棵完全二叉树,它反映了一系列“淘汰赛”的结果:叶子代表参加比赛的n个选手,每个内部结点代表由该结点的孩子结点所代表的选手中的胜者,显然,树的根结点就代表了淘汰赛的冠军。请回答下列问题:

(1)这一系列的淘汰赛中比赛的总场数是多少

(2)设计一个高效的算法,它能够利用比赛中产生的信息确定亚军。

(1)因为n人进行淘汰赛,要淘汰n-1人,所有要进行n-1场比赛。 (2)

10. 在120枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重。可以通过一架天平来任意比较两组硬币,最坏情况下,能不能只比较5次就检测出这枚假币

将120枚平均分为三组,记为:A,B,C;先将A,B比较,如果A,B重量不同(假如B比A重),再将B与C比较,如果B,C相同,则A有假币;如果B,C不同,再将A,C比较,如果A,C相同,则B有假币;如果A,C不同,则B有假币;如果A,B相同,则C有假币;

联系合同范文客服:xxxxx#qq.com(#替换为@)