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


当前回答

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

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

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

为了回答这个问题:

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

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

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

其他回答

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

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

下面是一个有趣的类比

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

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

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

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

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

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

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

在动态规划中,

没有递归的开销,维护表的开销也更少。 表访问的规则模式可用于减少时间或空间需求。

在记忆中,

有些子问题不需要解决。

动态规划通常被称为记忆!

Memoization is the top-down technique(start solving the given problem by breaking it down) and dynamic programming is a bottom-up technique(start solving from the trivial sub-problem, up towards the given problem) DP finds the solution by starting from the base case(s) and works its way upwards. DP solves all the sub-problems, because it does it bottom-up Unlike Memoization, which solves only the needed sub-problems DP has the potential to transform exponential-time brute-force solutions into polynomial-time algorithms. DP may be much more efficient because its iterative On the contrary, Memoization must pay for the (often significant) overhead due to recursion.

简单来说, 记忆法使用自顶向下的方法来解决问题,即从核心(主要)问题开始,然后将其分解为子问题,并以类似的方式解决这些子问题。在这种方法中,同一子问题可能会多次出现,消耗更多的CPU周期,从而增加时间复杂度。而在动态规划中,同一子问题不会求解多次,而是利用其先验结果来优化解。

我想举个例子;

问题:

你正在爬楼梯。到达顶端需要n步。 每次你可以爬1或2级台阶。有多少不同的方式 你能爬到山顶吗?

带记忆的递归

通过这种方式,我们在memo数组的帮助下修剪(从树或灌木中去除多余的材料)递归树,并将递归树的大小减小到nn。

public class Solution {
    public int climbStairs(int n) {
        int memo[] = new int[n + 1];
        return climb_Stairs(0, n, memo);
    }
    public int climb_Stairs(int i, int n, int memo[]) {
        if (i > n) {
            return 0;
        }
        if (i == n) {
            return 1;
        }
        if (memo[i] > 0) {
            return memo[i];
        }
        memo[i] = climb_Stairs(i + 1, n, memo) + climb_Stairs(i + 2, n, memo);
        return memo[i];
    }
}

动态规划

该问题可以分解为多个子问题,并且具有最优子结构的性质,即它的最优解可以由子问题的最优解有效地构造出来,因此可以采用动态规划的方法来求解该问题。

public class Solution {
    public int climbStairs(int n) {
        if (n == 1) {
            return 1;
        }
        int[] dp = new int[n + 1];
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }
}

示例摘自https://leetcode.com/problems/climbing-stairs/