【发布时间】:2021-02-06 11:33:00
【问题描述】:
问题必须具备两个关键属性才能使动态规划适用:最佳子结构和重叠子问题[1]。对于这个问题,我们将只关注后一个属性。
重叠子问题有多种定义,其中两种是:
- 如果一个问题可以分解成可以重复使用多次的子问题或该问题的递归算法一遍又一遍地解决相同的子问题,而不是总是生成新的子问题 [2].
- 要应用动态规划,优化问题必须具备的第二个要素是子问题的空间必须“小”,即问题的递归算法一遍又一遍地解决相同的子问题,而不是总是生成新的子问题(CLRS 的算法简介)
如果找到解决方案涉及多次解决相同的子问题,这两个定义(以及互联网上的许多其他定义)似乎都归结为具有重叠子问题的问题。换句话说,在寻找原始问题的解决方案的过程中,有许多小的子问题被计算了很多次。一个经典的例子是斐波那契算法,很多例子用来让人们理解这个属性。
直到几天前,生活还很美好,直到我发现 Kadane 的算法让我质疑重叠子问题的定义。这主要是因为人们对它是否是DP算法有不同的看法:
- Dynamic programming aspect in Kadane's algorithm
- Is Kadane's algorithm consider DP or not? And how to implement it recursively?
- Is Kadane's Algorithm Greedy or Optimised DP?
- Dynamic Programming vs Memoization (see my comment)
有人不认为 Kadane 的算法是 DP 算法的最令人信服的原因是每个子问题在递归实现[3] 中只会出现并被计算一次,因此它不需要重叠子问题属性。然而,网上很多文章都认为 Kadane 的算法是一种 DP 算法,这让我对重叠子问题的理解首先产生了疑问。
人们似乎对重叠子问题属性的解释不同。用斐波那契算法等简单问题很容易看出这一点,但是一旦你介绍了 Kadane 算法,事情就会变得非常不清楚。如果有人能提供进一步的解释,我将不胜感激。
【问题讨论】:
-
我认为您不必过分关注给定算法是否符合“动态编程”的条件。 “动态编程”作为设计算法的范例很有帮助。作为现有算法的标签,它没有用处。您以斐波那契数列为例。许多人会不同意仅将前两个值保留在内存中的斐波那契实现是否符合“动态编程”的条件。
标签: algorithm dynamic-programming fibonacci divide-and-conquer kadanes-algorithm