首页 > 技术文章 > 一只青蛙跳出来的分治法、回溯法与动态规划

genialx 2018-12-28 16:32 原文

从2018年7月份开始,基础薄弱的我从0开始刷LeetCode题目。目的性很明确,也很简单——就是为了提高解决问题的思考实践能力,也为了提升自己的核心竞争力。也许,牛人会觉得这并不算什么竞争力。是的,我同意的。但,这是我目前能做的比较基础的事情罢了。

迄今(2018年12月28日)为止,已经刷了108道题目。顺序基本上是按照出现的频率(Frequency)来刷的,这个频率在LeetCode上需要订阅后才可以看得到。那么在刷了108道题目后,有那么一些题目会觉得“似曾相识”了,也会有一种触类旁通的感觉了。所以,我觉得应该适当放慢刷题的速度,同时做做总结了。

所以,计划了一项视频解说计划,在YouTubehB站都建立了《小旭解说算法之路》的频道,欢迎订阅,多多提建议。

那么,进入正题。经过了108道题的历练之后,我来说说对于分治法、回溯法和动态规划的理解。

我觉得他们三者是一个相互有交集的概念,并不是相互完全独立的。至于为什么不是完全独立的,在分别说说这三种方法的解决思路后,我们再终结一下。

分治法(Divide and Conquer)

分治法是解决规模庞大的问题的很好的思路,他通过降低问题的规模,形成若干个规模更小但形式相同的子问题,进行递归求解。在求解过后,将各个子问题的解合并起来,形成原问题的解。

那么它的大致流程主要分成三步:

  • 分解(Divide)将大规模的问题分解成若干个规模更小但形式相同的子问题
  • 解决(Conquer)如果当前问题的规模足够小,并可以直接解决的话,那么直接解决并返回解。否则,继续进行分解并递归求解分解后的子问题。
  • 合并(Merge)将各个子问题合并,最终形成原问题的解。

所以,明确了三步之后,还要明确一件事件——实现方式:递归法。

分治法一般来说会采用递归法来进行实现,当然,利用迭代法(比如for、while)也是可以的。

所以,我们往往看到的递归算法从广义上来说都是分治法。无非就是有些递归算法将问题分解了若干个子问题,然而有些递归算法将问题分解成了一个子问题。那么有些作者会称作前者是分治法,后者是减治法。

其实,这个概念真的非常非常重要。在面对很多问题的时候,都可以用这种思路去思考。那么其中思考的一个非常重要的一点就是递归算法中的边界(跳出)条件的判定。

只要,我们想明白了求解子问题过程中的边界条件,那么问题就会很清晰,并且很容易地写出程序来。否则,模糊的边界条件,会导致整个递归算法进入到“死循环”的尴尬地步。

举个例子

青蛙

推荐阅读