【从零学习经典算法系列】分治与递归1——递归表达式与解法初步

对于像我这种情况,之前没怎么接触过算法或者只是简单了解并没有认识到算法的重要性的,终于下定决心要认认真真、踏踏实实去学习一个个经典算法,我希望这对于未来是非常重要的第一步。通过博客的方式来深入思考,督促自己,也希望在此过程证有和我一样,非计算机专业出身的同学能一起交流,共同体会算法的魅力。

算法是计算机的灵魂,它作为一种思想,使得我们的思维变得更清晰、更有逻辑。也许是现在变化太快,层出不穷的炫目技术、快餐速成的编程培训或者封装良好的算法接口,让很多像我一样只想盲目去写程序,却又没有清晰的思维和经过试验分析的解决方案。只有把握抽象层面的算法分析,才能不因外表的变化发展而过时淘汰,也才能对得起自己珍贵的时间。

于是,让我开始上路吧。

1、分而治之策略

比如足球世界杯,我们要通过世界杯决出世界上最好的一支球队,于是通过各大洲的分区比赛选出几支球队,再在这世界杯的32强决一雌雄。把一个大问题(全球各国家足球队选择水平能力最强的一支)分解成多个类型,相同规模,相对更小的小问题(各个赛区的强队),再分别解决更小的问题(小组赛、淘汰赛的角逐),最终使得一个大问题迎刃而解,这就是分治策略

分治策略可概括为以下步骤:

(1)分解(Divide):将问题分解为若干个小的子问题。每个子问题与大问题同型,但规模小。

(2)解决(Conquer):递归解决子问题。(递归是彰显分治优势的放大器,仅仅进行一次分治策略,也许改善的效果很小,但递归的进行分解下去,把问题分解到微不足道的境地,子问题的解即可用常数时间求得

(3)合并(Combine):将子问题的解答合并,获得大问题的解答。

在分而治之的策略下,所有工作被设定为分解部分、递归部分和合并部分。而整体的时间复杂度由这三部分的时间复杂度之和构成。

由于不断递归,最后的子问题变得极为简单,以至于其时间复杂度在整个策略上的比重微乎其微。因此,分而治之策略的真正成本实际在分解与合并两个部分上,即问题在需要分解多少次,每次分解的子问题数是多少?需要合并多少次,每次分解与合并需要的时间是多少?

2、递归表达式与递归树

一般来说,分支策略将一个大的复杂的问题划分为a个同型的子问题,这些子问题的规模是n/b。如果一直递归分解下去,可得到描述算法时间复杂度的递归表达式:

《【从零学习经典算法系列】分治与递归1——递归表达式与解法初步》

这里,b是每次分解时问题规模减小的因子,a是每次分解时产生的子问题个数,f(n)是分解与合并a个大小为n/b的子问题的成本。

而递归树是抽象的递归表达式具体化的图形表示,它给出的是一个算法递归执行的成本模型。该模型以输入规模为n开始,一层一层分解,直到输入规模变为1为止。

《【从零学习经典算法系列】分治与递归1——递归表达式与解法初步》

图1 递归树图例

3、替换法

替换法是先才某个界存在,再用数学归纳法证明正确性,通过解决表达式中的常数c来验证答案。

举例来说明,比如我们需要用替换法来证明T(n) = T(n/4)+T(n/2)+n^2的解释Θ(n^2),即分别证明T(n)=O(n^2)和T(n)=Ω(n^2)。

《【从零学习经典算法系列】分治与递归1——递归表达式与解法初步》

图2 替换法举例

小结:

本文就分治思想和递归表达式作了一简单介绍,就递归表达式的解法,可以用递归树或者替换法来求解,但是上述两种方法会有相应的缺点,导致求解的结果不准确或者误解,下一篇文章将介绍主方法(master method),并给出证明。


补充:

在求时间复杂度的很多时候都会用到这个公式a^logb(c) = c^logb(a),从维基百科中得知该公式是对数换底公式的一个推论,但网络上没有找到该公式的证明或者很好的解释,于是我自己证了一下,分享给大家。

对数换底公式推论的证明

《【从零学习经典算法系列】分治与递归1——递归表达式与解法初步》

转载请标明出处,原文地址:http://blog.csdn.net/jasonding1354/article/details/37334651

参考资料:

《算法之道(第2版)》,邹恒明著,机械工业出版社

《算法导论(原书第2版)》,机械工业出版社

麻省理工学院公开课:算法导论


    原文作者:递归与分治算法
    原文地址: https://blog.csdn.net/jasonding1354/article/details/37334651
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞