algorithm - 如何将以下递归转换为自上而下的动态规划?

标签 algorithm dynamic-programming

我正在尝试解决 Maximum Product Subarray来自 leetcode 的问题。

问题描述是:给定一个整数数组,找到数组中至少包含一个数且乘积最大的连续子数组。

示例:输入:[2,3,-2,4],输出:6

为了解决这个问题,我使用了以下逻辑:让 f(p,n) 输出正确的结果,直到结果为 p 的数组的索引 n 为止。所以递归是:

f(p,n) = p // if(n=a.length)
f(p,n) = max( p, f(p*a[n], n+1), f(a[n], n+1) ) // otherwise

这适用于常规递归(下面的代码)。

private int f(int[] a, int p, int n) {
    if(n==a.length)
        return p;
    else
        return max(p, f(a, p*a[n], n+1), f(a, a[n], n+1));
}

但是我无法将其转换为自上而下的动态规划。我一直用来将递归程序转换为使用自上而下 DP 的方法是:

  • 初始化缓存(我将使用数组)
  • 如果索引 'n' 处的缓存已被填充,则返回该值作为结果
  • 否则递归并将结果存储在缓存中
    • 从缓存中返回值。

这是我一直在使用的一种通用方法,它适用于我做过的大多数 dp 问题,但不适用于这个问题。

使用这种方法的(不正确的)代码如下所示:

private int f(int[] a, int p, int n, int[] dp) {
    if(dp[n]!=0)
        return dp[n];
    if(n==a.length)
        dp[n] = p;
    else
        dp[n] = max(p, f_m(a, p*a[n], n+1, dp), f_m(a, a[n], n+1, dp));
    return dp[n];
}

我从主函数调用函数如下:

// int x = f(a, a[0], 1, dp); - for incorrect top-down dp attempt
// int x = f(a, a[0], 1); - for regular recursion

它不起作用的一个例子是:[3,-1,4]。这里它错误地输出了 3 而不是 4。

据我了解,问题是因为两个子问题都引用了 DP 数组的同一个 n+1 索引,所以只解决了 1 个子问题,这导致了错误的答案。

所以我的问题是:

如何将这个循环转换为自上而下的 DP 程序?对于这种情况,是否有我可以遵循的通用方法?

最佳答案

您的dp 状态取决于当前索引n 和当前结果p。因此,您需要将结果存储在 2D 数组中,而不是仅使用 1D 数组作为索引。

private int f(int[] a, int p, int n, int[] dp) {
    if(dp[n][p]!=0)
        return dp[n][p];
    if(n==a.length)
        dp[n][p] = p;
    else
        dp[n][p] = max(p, f_m(a, p*a[n], n+1, dp), f_m(a, a[n], n+1, dp));
    return dp[n][p];
}

关于algorithm - 如何将以下递归转换为自上而下的动态规划?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54598055/

相关文章:

algorithm - 查找算法 : Reconstruct a sequence with the minimum length combination of disjointed subsequences chosen from a list of subsequences

algorithm - 如何从 n 个元素中找到 k-排列的索引?

algorithm - 2个字符串之间的差异

python - 找出所有可能的变化排列

algorithm - 修改硬币找零的伪多项式时间算法

algorithm - 使用 Dijkstra 算法的负权重

c++ - 有向无环图的 C/C++ 实现

python - 如何合并两个链表

python - 计算列表中的所有序列

algorithm - 带有哈希数组的背包 DP