分治递归、动态规划、贪心
《算法之道》提到,问题的基本求解理念有三种——分治与递归、动态规划、贪心。
分治与递归所能处理的问题最多,对问题的性质没有要求(不过可能会出现很复杂的分治情况),所需要求解的子问题数最多,而且如果子问题有重复,则每一次都要重复求解;
动态规划叫做Dynamic Programming,这里的Programming的意思不是编程而是查表,动态规划不如翻译成动态查表更容易理解些,规划这个词太空了。动态规划的思想就是发现在分治递归求解中有很多子问题都被求解了多次从而造成了复杂度的上升,如果只求解一次然后存储起来再备后来查表,就可以解决这个问题。所以将递归的自顶向下改为自底向上就得到了动态规划的思路,如果仍然使用自顶向下的思路但是每次求解一个子问题的时候查看是否已经求解过(自然也需要将子问题的解存储起来)则得到了“存储化递归”的解法,复杂度与动态规划只有常数差别。
动态规划要处理的问题要求问题具有最优子结构(即最优解包含子问题的最优解),是一种自底向上的求解思路,与递归正好相反,每次求解到一个阶段时,该阶段求解所依赖的子问题已经完全求解完毕,因此每一步的求解都是在直到全部所需信息的情况下进行的,因此可以得到全局最优解。
贪心算法如果想要得到最优解,需要对问题性质有更严格的要求,除了要有最优子结构外,还要求问题具有贪婪选择性质。具体来说就是:贪心是一种策略,即每一步都要选择当前看来最好的,做完此选择后便将问题化为一个(仅仅一个)子问题,这是一个顺序的求解过程,每一步都是单独考虑,只考虑局部最优,因为并没有完成对之后子问题的求解,所以贪心算法不能完成对整个解空间的搜索,因此通常不能得到最优解。除非问题具有贪婪选择性质。所谓贪婪选择性质就是问题经过一次贪婪选择后只能形成一个子问题,这样求解空间实际上就是一个线性的空间,贪心算法可以得到最优解。
也许有些问题初看起来并不具备该性质而需要一定的转化,这方面一个经典的例子是教室排课问题:给出N门课的开始时间和结束时间,如何排课才能让尽可能多的课在一个教室里面上?贪心策略是每次选择可以选择的课(即开始时间晚于当前已排课程中结束最晚的课的结束时间)里结束时间最早的课。
十月 7th, 2010 at 2:03 下午
[...] 这三个算法的本质都是贪心,三个问题都具有贪婪选择性质使得使用贪心算法可以得到最优解。 [...]
十月 7th, 2010 at 3:33 下午
以前我对DP有这么一种理解,控制对子问题的求解顺序使得每个字问题只需要求解一次。现在看来这个理解有些拖沓,实际上就是四个字“自底向上”。递归是典型的自顶向下,回溯后还要再向下求解,自然可能将子问题进行重复求解。而动态规划的自底向上+查表可以保证每个子问题只被求解一次。