-
贪心算法原理
贪心算法就是做出一系列选择来使原问题达到最优解。在每一个决策点,都是做出当前看来的最优选择,比如在活动选择问题里面,我们总是在一个问题的基础上选择结束时间最早的活动,之后再在剩下活动的基础上选出结束时间最早的活动,以此类推,直到没有活动可以进行选择。但是遗憾的是这种算法并不是总能得到最优解,并且是否能得到最优解还取决于对于贪心策略的选择。
一般来说,设计贪心算法涉及到下面几个步骤:
- 确定问题的最优子结构
- 基于问题的最优子结构设计一个递归算法
- 证明我们做出的贪心选择,只剩下一个子问题
- 证明贪心选择总是安全的
- 设计一个递归算法实现贪心策略
- 将贪心算法转化为迭代算法
例如,在活动选择问题中,我们首先定义了子问题,其中i和j都是可变的。然后我们发现,如果总是做出贪心选择,则可以将子问题限定为的形式。然后,可以证明,贪心选择(中最早结束的活动)与剩余兼容活动集的最优解组合在一起,就会得到的最优解。
更一般的来说,我们可以将贪心算法的设计步骤简述为下面几步:
- 将最优化问题简化为这样的形式:做出一个选择以后,只剩下一个子问题需要求解
- 证明在做出贪心选择以后,原问题总是存在最优解,即贪心选择总是安全的
- 证明在做出贪心选择以后,剩下的子问题满足性质:其最优解与做出选择的组合在一起得到原问题的最优解,即最优子结构
-
两个关键要素
没有一般化的规则来说明贪心算法是否最优,但有两个基本要点:贪心选择性质和最优子结构。
1.贪心选择性质
第一个关键要素就是贪心选择性质:我们可以做出局部最优选择来构造全局最优解。也就是说,我们在做出选择时,总是以当前的情况为基础做出最优选择的,而不用考虑子问题的解。
这也是和动态规划最大的不同之处。在动态规划中,在每次做出一个选择的时候总是要将所有选择进行比较才能确定到底采用哪一种选择,而这种选择的参考依据是以子问题的解为基础的,所以动态规划总是采用自底向上的方法,先得到子问题的解,再通过子问题的解构造原问题的解。就算是自顶而下的算法也是先求出子问题的解。在贪心算法中,我们总是在原问题的基础上做出一个选择,然后求解剩下的唯一子问题,贪心算法从来都不依赖子问题的解,不过有可能会依赖上一次做出的选择,所以贪心算法是自顶而下的。
2.最优子结构
如果一个问题的最优解包含其子问题的最优解,那么就称这个问题具有最优子结构性质。
将子问题的最优解与贪心选择组合在一起就能生成原问题的最优解。