记忆和动态规划的区别是什么?我认为动态规划是记忆的一个子集。对吗?


当前回答

这是一个记忆和DP从斐波那契数问题写在Java的例子。

这里的动态编程不涉及递归,因为它不受执行堆栈的限制,所以结果更快,可以计算出更高的值。

public class Solution {

 public static long fibonacciMemoization(int i) {
    return fibonacciMemoization(i, new long[i + 1]);
 }

 public static long fibonacciMemoization(int i, long[] memo) {
    if (i <= 1) {
        return 1;
    }
    if (memo[i] != 0) {
        return memo[i];
    }
    long val = fibonacciMemoization(i - 1, memo) + fibonacciMemoization(i - 2, memo);
    memo[i] = val;
    return val;
 }

 public static long fibonacciDynamicPrograming(int i) {
    if (i <= 1) {
        return i;
    }
    long[] memo = new long[i + 1];
    memo[0] = 1;
    memo[1] = 1;
    memo[2] = 2;
    for (int j = 3; j <= i; j++) {
        memo[j] = memo[j - 1] + memo[j - 2];
    }
    return memo[i];
 }

 public static void main(String[] args) {
    System.out.println("Fibonacci with Dynamic Programing");
    System.out.println(fibonacciDynamicPrograming(10));
    System.out.println(fibonacciDynamicPrograming(1_000_000));

    System.out.println("Fibonacci with Memoization");
    System.out.println(fibonacciMemoization(10));
    System.out.println(fibonacciMemoization(1_000_000)); //stackoverflow exception
 }
}

其他回答

动态规划是一种求解给定问题的算法范式 将复杂问题分解为子问题并存储结果 以避免再次计算相同的结果。

http://www.geeksforgeeks.org/dynamic-programming-set-1/

记忆是一种跟踪以前解决的解决方案的简单方法(通常实现为哈希键值对,而不是通常基于数组的制表),这样当它们再次遇到时就不会重新计算。它可以在自底向上或自顶向下的方法中使用。

请参阅关于记忆和制表的讨论。

动态规划是一种通过求解递归关系/递归并通过制表或记忆存储先前找到的解来解决某些类型问题的方法。记忆是一种跟踪以前解决问题的解决方案的方法,可以与任何对于给定输入集具有唯一确定性解决方案的函数一起使用。

(1)从概念上讲,记忆和DP其实是一回事。因为:考虑DP的定义:“重叠子问题”和“最优子结构”。记忆完全具备这两点。

(2)在递归较深的情况下,记忆是DP方法,存在栈溢出风险。DP自下而上没有这种风险。

(3)记忆需要一个哈希表。额外的空间和查找时间。

为了回答这个问题:

-从概念上讲,(1)意味着它们是一样的东西。

-考虑(2),如果你真的想,记忆化是DP的一个子集,从某种意义上说,可以通过记忆化解决的问题可以通过DP解决,但是可以通过DP解决的问题可能无法通过记忆化解决(因为它可能会堆栈溢出)。

把(3)考虑在内,它们在性能上有微小的差异。

记忆和动态规划都只解决单个子问题一次。

记忆化使用递归并自顶向下工作,而动态规划则相反,自底向上解决问题。

下面是一个有趣的类比

自上而下-首先你说我将接管世界。你会怎么做呢?你说我会先拿下亚洲。你会怎么做呢?我会先接管印度。我会成为德里的首席部长,等等。

自下而上——你说我会成为德里的首席部长。然后我会接管印度,然后是亚洲所有其他国家,最后我会接管全世界。

从维基百科:

记忆有关

在计算中,记忆是一种主要使用的优化技术 通过函数调用来加速计算机程序,避免重复 对先前处理过的输入的结果的计算。

动态规划

在数学和计算机科学中,动态规划是一种方法 把复杂的问题分解成更简单的问题 子问题。

当把一个问题分解成更小/更简单的子问题时,我们经常会不止一次遇到相同的子问题——所以我们使用Memoization来保存以前的计算结果,这样我们就不需要重复它们了。

动态编程经常遇到使用内存是有意义的情况,但您可以使用任何一种技术而不必使用另一种技术。

动态规划(DP)和记忆化之间有一些相似之处,在大多数情况下,您可以通过记忆实现动态规划过程,反之亦然。但它们确实有一些区别,你应该在决定使用哪种方法时查看它们:

Memoization is a top-down approach during which you decompose a big problem into smaller-size subproblems with the same properties and when the size is small enough you can easily solve it by bruteforcing. Dynamic Programming is a bottom-up approach during which you firstly calculate the answer of small cases and then use them to construct the answer of big cases. During coding, usually memoization is implemented by recursion while dynamic programming does calculation by iteration. So if you have carefully calculate the space and time complexity of your algorithm, using dynamic-programming-style implementation can offer you better performance. There do exist situations where using memoization has advantages. Dynamic programming needs to calculate every subproblem because it doesn't know which one will be useful in the future. But memoization only calculate the subproblems related to the original problem. Sometimes you may design a DP algorithm with theoretically tremendous amount of dp status. But by careful analyses you find that only an acceptable amount of them will be used. In this situation it's preferred to use memoization to avoid huge execution time.