算法设计与分析第二章——递归与分治法课后题分析题

 

汉诺塔的递归算法hanoi(n-1,a,b,c)是将圆盘上的n-1个圆盘从a借助c移动到b,需要分为a移动到c,c移动到b两步

 也就是说实际上圆盘的运动顺序是从起始位置A移动到C,但是需要借助B,先让A柱子上的n-1圆盘移动到B,再把n圆盘放到C,然后再调用一次

hanoi(n-1,b,c,a)再将B上的n-1圆盘借助A移动到C。这样就实现了圆盘的整体移动,由于递归调用,就应该是这样的代码

hanoi(n,a,b,c)//a移动到b分为a移动到c,c移动到b两步

{

        hanoi(n-1,a,c,b)//先从a移动到c需要借助b

        move(a,b)//将圆盘n从a移动到b

        hanoi(n-1,c,b,a)//从c移动到b需要借助a

}

 而不用递归,我们就应该按照上图的顺序,假设我使用循环语句,n层的汉诺塔我们就应该循环n次,而每次循环都要使得起点借助另一根柱子到达终点。依旧用算法hanoi(n,a,b,c),不过这里的n我们视作移动的圆盘编号,因为顺序移动只能从小到大移动了。那我们应该

hanoi(1,a,c,b)

hanoi(1,c,b,a)//虽然第一步完全不需要辅助柱子

hanoi(2,a,c,b)//移动圆盘2

hanoi(1,b,a,c)

hanoi(2,c,b,a)

hanoi(1,a,c,b)

hanoi(1,c,b,a)

 我们发现粗体部分重复了一边,而粗体部分正是对1的汉诺塔算法。通过数学归纳法不难得出,如果我们移动圆盘3,那么其中一定需要重复圆盘2部分的汉诺塔算法。而n操作调用n-1操作这本身就是递归。

再看红色部分,我们把2通过(a,c,b)放到了c,然后想把它放到b,但是此时1还在b,因此我们要把1从b移动到a,从形式上来看,圆盘总是按照abc的顺时针移动的,而当后面的圆盘移动了之后,前面的圆盘就要移动才能使得后面的圆盘再次移动。因此我们的1经历了(a,c,b) ——(c,b,a)——(b,a,c)——(a,c,b)我们发现构成了一个循环,而这个循环正是所有圆盘在汉诺塔的移动中都会遵守的规律,直到最后一个圆盘1从(a,c,b) ——(c,b,a),此时全部圆盘就移动到了b上,因此我们认为汉诺塔的递归和非递归本质上的一回事。
 


 (二分查找中的数列一定是有序的,举反例也要举出有序数列)

第一个算法 是错误的,假设有一行012345,我们要寻找5也就是a[5],那么经过顺序是

2(L=2),3(L=3),4(L=4)

接下来mid=(4+5)/2=4,此后就永远等于4

发生这种现象的根本原因就是折半查找每次都会将查找的距离减少一半,而假如mid指针的移动=(L+R)/2的话,其作用只能将L和R之间的距离缩小一半,当L和R的之间距离只剩0的时候,也就是L和R相邻的时候,就算再怎么缩小间距也还是0。

 看看语句

假设0123,要找到3,遍历顺序是12,当遍历到2时L=2!<3-1,此时退出,而a[left]=2。

因此找不到a[n-1]

 同样的问题,比如0123,需要找到3,遍历顺序为12,而L=2时,2+1=right,此时就需要退出了无法遍历到3,因此找不到x=a[n-1]

 虽然R=mid-1,但是L依然还是第一题的老毛病。假设0123,我要在其中寻找3,依旧和第一题一样陷入了死循环,但是如果x <a[mid]时不会出现这个问题。

 这一题是正确的,他和之前的第4题区别就在于mid是向上取整而不是向下取整的,这样就不会陷入left不动的死循环之中。这个算法用left的位置来保存找到的x的值,当x<a[mid],说明x在mid左边,使R=mid-1;反之若x>=a[mid],则将L=mid,如果x=a[L]那就是已经找到了,L也无需移动,如果x>a[L]则移动L,随着mid的来回移动,反正x是在L的右边,mid迟早找到x的位置并保存在L。最后如果x==a[L]就返回L,否则就是没找到返回-1

错误,5是正确的,如果用left记录x的位置,left不该比mid大

错误,又回到了前几题的错误,如果从右往左搜索,right最多只能到达a[1]然后陷入死循环,无法查询a[0]  


 

其实就是L指针右移的时候之前更新元素i的位置为L。R 左移之前更新元素j的位置为R。更新完在移动。当找到元素x的位置直接将i=j=mid就行了,像上面那题直接找到x输出就行了,没必要这样子写的,直接输出还简单点。


 之前使用分治法分割大整数的时候,m和n长度差的不多,如果m比n小得多,分治反而不适合了,所以我们需要灵活地进行分治,我们只知道n很大,但是不知道m有多小,因此新的算法需要符合m越小,计算越简单,那么越不需要分段。m越大,计算越复杂,越需要分段。因为计算机相乘究其本质是加法。因此答案给出将v分成n/m段,将m作为分母就符合我们需要的特点了。


 证明过程较复杂,可以简单看看,

 

 

 其实就是将大整数乘法分割后看作由关于w(xi)的多项式所构成的非齐次线性方程组。考研不大可能考到吧。但是可以看看证明思路。

后面的题目还是太多了,主要中心在算法题,以后分析题有时间回头再补 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值