如果要转载,需要注明出处: http://blog.csdn.net/xiazdong
在算法导论第三版中将算法导论第二版的“递归式”章节改为了“分治法”,而且加入了“Maximum Subarray”和“strassen矩阵计算”两个问题。
本文依然会在讲解中穿插一些习题,以更好地理解分治法。
一、递归式介绍
分治法其实在很多地方都会看到,比如归并排序、快速排序等都是运用分治法解决。
而每个分治法问题通常都能够用“递归式”表示。
比如归并排序的递归式如下:
当然一般的书中通常都会写成:
这样写的原因是简化思想,即后一种表示假设“n是2的幂次”。并且这两种表示的结果都是一样的。
递归式要注意:
一定不要忘了边界条件,即n=1时的T(1)值,虽然通常来说T(1)=1。
递归式的性质:
现在我们来证明这个结论:第一个递归式和第二个递归式的结果一样。
第二个递归式通过主定理就能够得出,因此不证明了。
第一个递归式我们用代换法验证。
第一步:证明T(n)=O(nlgn)
第二步是证明T(n)=Ω(nlgn)
因此得证。
递归式的三种解法:
(1)Substitution Method:主要用于验证假设的解是否正确。(注意要证明边界条件)
(2)Recursive Tree:用于估算递归式的解。
(3)Master Method:用于解一些简单的递归式的解。(主定理的证明是用递归树证明的,可以不必深究)
通常:简单的递归式用主定理做,烦的递归式先用递归树估计,再用代换法验证。
递归树因为比较简单,因此这里不做讲解。
主定理我就简单的列出公式:
注意:
在(1)、(2)、(3)之间是有空隙的。
比如
当出现:T(n)=2T(n/2)+nlgn时就不能使用第三种情况,因为f(n)=nlgn,他不是多项式大于n,因此不是第三种情况,但是能用第二种情况。
接下来我们举一个例子来更明确怎么解递归式。(出自算法导论4-4(f))
二、分治法介绍
定义:将原问题分解为多个独立的子问题,分别进行求解,且子问题的形式和原问题一致,只是规模减少了。
分治法一个比较容易遗忘的是:Base case,即什么时候递归,而什么时候停止。比如BinarySearch的Base case是p<=q,当开始位置大于结束位置时就停止。
分治法的三个步骤:
(1)Divide:将原问题分解为多个子问题。
(2)Conquer:对子问题递归求解。
(3)Combine:将子问题合并为原问题的解。
比如归并排序:
Divide步骤是 m=(p+q)/2
Conquer步骤是
merge_sort
(A,p,m)和merge_sort(A,m+1,q)
Combine步骤是merge(A,p,m,q)
比如二分查找:
Divide步骤是 m= (p+q)/2
Conquer步骤是BinarySearch(A,p,m-1)或BinarySearch(A,m+1,q)
Combine步骤是NIL。
而假设Divide需要f(n)时间,Combine需要g(n)时间,分解为a个大小为n/b的子问题,则递归式表示为:T(n)=aT(n/b)+f(n)+g(n)
最后给出一个分治法的例子:
问题:给定一个大小为n的数组,且数组的数据分布为先上升再下降,即一开始数据是严格增大的,后来数据是严格下降的,我们需要用O(lgn)查找到数组中的最大值。
思路:每次在数组中央取两个数a和b,如果a<b,则说明还处在上升阶段,则最大值在A[b...n]中;如果a>b,则说明已经在下降阶段,则最大值在A[1...a]。
伪代码:
接下来的一道题目也比较经典,是算法导论的思考题4-6,这里我们只做b)小题。
解答:b)
设j为输出”好好“的对数。
思路:两两测试,如果是输出”坏好,好坏,坏坏“,则全扔掉,因为每次扔掉的至少有一个坏的,如果是输出”好好“,则留一个,当n为奇数时,会出现一个孤单芯片,如果j为奇数,则扔掉孤单芯片;如果j为偶数,则保留孤单芯片。当n为偶数时不会有孤单芯片。
证明:
去掉那些”
坏好,好坏,坏坏
“的后,
当n为奇数时,则最后肯定有一个孤单芯片。
当j为奇数,则说明好芯片相互测试的对数至少比坏芯片相互测试的对数多1.因此不管剩余什么,只要扔掉,则最终好芯片个数肯定比坏芯片个数多。
当j为偶数,则说明好芯片相互
测试的对数至少比坏芯片相互测试的对数一样。
当孤单芯片是好芯片,则保留后,好芯片比坏芯片多。
当孤单芯片是坏芯片,则能够进一步确定:好芯片相互测试的对数至少比坏芯片相互测试的对数多2对(性质1,后面证),因此就算保留了坏的,最终好芯片仍然比坏芯片多。
性质1证明:因为j为偶数,则如果
好芯片相互
测试的对数至少比坏芯片相互测试的对数一样,则在输出”好好“的芯片中,除了孤单芯片外,好芯片个数是等于坏芯片个数,但是加上孤单芯片后,则坏芯片就比好芯片多了,而如果当输出
”
坏好,好坏,坏坏
“又遇到了最坏情况:一好一坏,则最终说明n中好芯片比坏芯片少,因此与条件矛盾。
当n为偶数时,则最后没有孤单芯片。不管j是偶数奇数,坏芯片
相互测试的对数至少比坏芯片相互测试的对数多1。因此最终好芯片比坏芯片多。