一、递归
1.概念:直接或间接的调用自身。
2.递归实现原理(个人理解):类似于栈,先进后出,递归先把一个问题分成n个规模,先将这n个问题按n,n-1,…….1,放入栈中,然后从1开始解,这是得到一个结果,返回给返回给2(第二层),第二层在此基础上计算,再返回一个值,最终到n,结果也就出来了。
3.说明:
(1)递归每一次调用自身,都会进一步得到最终结果,适用于具有一定规律,且可以将问题划分为多个与元问题相同的子问题。
(2)这类问题往往用递推可以解,但是你会发现在n不确定时无法入手,即便在n确定的情况下,如果n过大,则会导致递推的代码量十分臃肿。所以之所以用递归而非递推是由于一般递推的步骤过于繁琐。运用递归可以简化代码,但同样有缺点,就是问题规模很大时,问题计算的时间复杂度就会越高,总之就是效率不高,不适合处理子问题数量十分大的问题。
4.例子:
折半查找
二、分治策略
1.概念:将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同,递归的解这些子问题,然后将子问题合并得到原问题的解。
2.适用情况:
(1)整体问题难以解决,但问题的规模缩小到一定的规模就可以较容易地解决。
(2)问题可以分解为若干个规模较小的模式相同的子问题,即该问题具有最优子结构性质。
(3)合并问题分解出的子问题的解可以得到问题的解。
(4)问题所分解出的各个子问题之间是独立的,即子问题之间不存在公共的子问题。
3.说明:
分治法是对一些用普通递推难以解决的问题给出了一个有效的解决方法,但由于是以递归为基础的,所以缺点自然而然和上面一样,如果问题规模很大,则时间复杂度会很高。同时,分治法也有它相应的难点,其在于找到一种有效划分子问题的方法。这就需要多练习来找感觉了。
4.例子:
半数集
三、动态规划
1.概念:这个方法也是通过子问题来求解最终问题,但与分治法不同的是,这些子问题相互之间不独立,所以这时就需要在解决一个子问题后记录下它的值,在以后不管什么时候用到直接调用。避免重复计算,即在该计算中,填表是十分重要的。
2.适用情况:
(1)问题包含最优子结构性质:所谓最优子结构性质,就是当问题的最优解包含其子问题的的最优解。举个例子:在单源点最短路径中,如果1到5的最短路径为1->3->5,这时可以知道1到3的最优解为1->3。即后一步的最优解都包含上一步的最优解。
(2)子问题重叠性质:在解决问题的时候,往往会计算许多重复的子问题,为了避免这样,就需要把每次计算的结果放到一个表中。避免重复计算,当再次用到时,只是简单的查下表就可以了。
3.说明:与分治法一样,该方法也要每个子问题都要找,但由于子问题之间不相互独立,所以为了不重复解决子问题,动态规划法利用一个表来记录计算过的结果,这样节省了许多时间。
4.例子:
背包问题
四、贪心法
1.概念:贪心算法总是做出当前看来是最好的选择,它不从整体最优考虑,其所做出的选择只是在某种意义上的局部最优选择。
2.适用情况:
(1)贪心选择性质:所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优选择,即贪心选择来达到,这是贪心算法与动态规划的主要区别。
(2)最优子结构性质:与上面的含义相同。
3.说明:贪心算法实质就是通过局部最优来求解最终结果的最优,仅在当前状态下做出最好选择,然后再去解做出这个选择后产生的相应的子问题。贪心法并不每个问题都要计算,只选取局部最优,最终得到全局最优。但其有个明显的缺点那就是不可靠,有可能返回的是错误的结果,但这种几率一般比较小。
4.例子:
单源点最短路径
五、回溯法
1.概念:按照深度优先原则,每个节点都要找,只要是符合问题所约束的条件都可以。
六、分支限界法
1.概念:按照广度优先原则,只要找到符合约束条件的结果就停止搜索,返回结果。
七、随机化算法
1.概念:所谓随机化算法,就是通过随机产生的结果作为问题的输入,从而得出问题的解。
2.适用情况:
(1)一般隐式的用于完美散列和通用散列。
(2)测试大数是否是素数的随机化算法。
3.例子:
素性测试
注:
- 未完还带补充。
- 所做的分析都是笔者自己的见解,如有不正确还请见谅。
- 另外,如需更多代码请访问我的Github:https://github.com/Zxnaruto