动态规划的记忆法或制表法

Posted

技术标签:

【中文标题】动态规划的记忆法或制表法【英文标题】:Memoization or Tabulation approach for Dynamic programming 【发布时间】:2012-08-16 01:27:03 【问题描述】:

有很多问题可以使用动态编程来解决,例如最长的递增子序列。这个问题可以通过两种方法解决

    Memoization (Top Down) - 使用递归解决子问题并将结果存储在某个哈希表中。 制表法(自下而上) - 使用迭代方法解决问题,首先解决较小的子问题,然后在执行较大的问题时使用它。

我的问题是在时间和空间复杂度方面哪种方法更好?

【问题讨论】:

您的第二个选项并不是真正的动态编程,它更多的是减少和征服。这取决于问题的规模以及问题在分析方面试图解决的问题。 当然取决于问题。 如果有一个千篇一律的通用答案,生活会更简单,所有的教科书都会教你“正确”的方法。但没有一个普遍的答案。此外,这个词是“记忆”。没有“R”。 为什么叫memoization?当我们记住较小的子问题的结果时,记忆似乎是一个恰当的词。 @Mady en.wikipedia.org/wiki/Memoization#Etymology 【参考方案1】:

简答:取决于问题!

Memoization 通常需要更多的代码并且不那么直接,但在某些问题中具有计算优势,主要是那些你不需要需要计算整体的所有值的问题矩阵来得出答案。

制表 更直接,但可能会计算不必要的值。如果您确实需要计算所有值,则此方法通常更快,因为开销较小。

【讨论】:

【参考方案2】:

假设您使用相同的递归关系,自上而下的动态编程实现与自下而上的渐近实现相同。然而,由于在记忆中使用递归的开销,自底向上通常更有效。

【讨论】:

我有一个关于这个的问题。如果我们使用哈希集和记忆化来存储已经计算的值,那么在大多数情况下,记忆化不会像制表一样有效吗?【参考方案3】:

首先了解什么是动态规划? 如果手头的问题可以分解为解决方案也是最优的子问题,并且可以组合以达到原始/更大问题的解决方案。对于此类问题,我们可以应用动态规划。 它是通过将子问题的结果存储在程序内存中并重用它而不是在以后重新计算来解决问题的方法。

请记住,动态规划使用的理想情况是,您可以多次重复使用子问题的解决方案,否则,存储结果毫无意义。

现在,动态规划可以应用于自下而上的方法(Tabulation)自上而下的方法(Memoization)

制表:我们从计算最小子问题的解决方案开始,然后一次升级一个级别。基本上遵循自下而上的方法。 请注意,我们正在详尽地为每个子问题寻找解决方案,但不知道将来是否真的需要它们。

记忆:我们从最初的问题开始,并不断将其分解到我们知道其解决方案的基本案例。在大多数情况下,这种分解(自上而下的方法)是递归的。因此,如果问题是由于递归调用而使用每个步骤的子解决方案,则花费的时间会更慢。但是,在不需要所有子解决方案的情况下,Memoization 的性能优于 Tabulation。

我发现这个短视频很有帮助:https://youtu.be/p4VRynhZYIE

【讨论】:

【参考方案4】:

如果问题有overlapping sub-problems 属性,则使用Memoization,否则取决于问题

【讨论】:

对于重叠的子问题,我们也可以使用制表法。 是的,您可以使用,但记忆化消除了冗余计算 @arunmoezhi 制表也是如此。

以上是关于动态规划的记忆法或制表法的主要内容,如果未能解决你的问题,请参考以下文章

动态规划问题

阿牛的EOF牛肉串-记忆化搜索或动态规划

动态规划(普及组)

动态规划之记忆的作用

深入浅出理解动态规划 | 交叠子问题

§6-3 动态规划——离散型分配问题