而 贪心技术 则专注于扩展部分构建的解决方案,直到您找到完整问题的解决方案。然后说,它必须是 "该步骤上所有可行选择中的最佳本地选择"。
既然两者都涉及局部最优性,难道一个不属于另一个子集吗?
动态规划适用于具有以下特性的问题:
最优子结构意味着您可以贪婪地解决子问题并组合解决方案以解决更大的问题。动态规划与贪心算法的区别在于,动态规划存在重叠子问题,并使用记忆化来解决这些子问题。 "记忆化"是一种技术,其中将子问题的解用于更快地解决其他子问题。
这个答案引起了一些关注,所以我会举些例子。
考虑问题“用美元、镍和便士找零钱”。 这是一个贪心问题。 它表现出最优子结构,因为您可以解决美元的数量。 然后,解决镍的数量。 然后是便士的数量。 然后,您可以有效地组合这些子问题的解决方案。它实际上没有表现出重叠子问题,因为解决每个子问题对其他问题的帮助不大(也许有点)。
考虑问题“斐波那契数列”。 它表现出最优子结构,因为您可以通过添加高效地从F(9)和F(8)解决F(10)。 这些子问题重叠,因为它们都共享F(7)。 如果在解决F(8)时记忆化F(7)的结果,则可以更快地解决F(9)。
针对评论关于动态规划与“重新考虑决策”有关的评论:这显然不适用于任何线性动态规划算法,例如最大子数组问题或上面的斐波那契问题。
基本上,想象一下具有最优子结构的问题作为有向无环图,其节点表示子问题(其中整个问题由一个入度为零的节点表示),其有向边表示子问题之间的依赖关系。 然后,贪心问题是一个树(除根节点外的所有节点都具有单位入度)。 动态规划问题具有一些入度大于1的节点。 这说明了重叠子问题。
不同之处在于动态规划要求你记住较小状态的答案,而贪心算法在当前状态中只需要全部必需的信息。当然,两者也有些交集。
DP算法利用这样一个事实(对于某些问题)——问题规模为n
的最优解由问题规模为n'<n
的最优解组成,并利用此方法自下而上地构建解决方案,从最小的问题到所需的规模。
它很好地符合了递归原理(将问题缩小为更小的子问题,并进行递归调用),事实上,DP解决方案通常表示为递归公式。
贪心算法看着一个局部点并根据该点的数据做出一些选择。对于某些问题(例如没有负权重的最短路径),这种局部选择将导致最优解。
两种方法之间差异的一个很好的例子是最短路径问题:
贪心算法:
动态规划: