【问题标题】:Is Kadane's Algorithm Greedy or Optimised DP?Kadane 的算法是贪心的还是优化的 DP?
【发布时间】:2015-09-18 06:04:40
【问题描述】:

我觉得 Kadane 的算法是最大子数组问题的真正动态规划解决方案的修改版。为什么我会这么觉得? 我觉得是因为计算最大子数组的方式可以采取:

for(i=0;i<N;i++)
    {
        DP[i][A[i]]=true;
        for(j= -ve maximum ;j<= +ve maximum ;j++)
        if(DP[i-1][j])
            DP[i][j+A[i]]=true;
    }

如果有可能用以 i-1 个元素结尾的子数组形成 j,则我可以使用第 i 个元素形成 j+A[i]并且还通过在第 i 个位置开始一个子数组来单独形成 A[i] 最后我们可以在这个 DP 数组中搜索标记为 true 的最大值 j!

注意:DP[i][j] 表示是否可以使用以 i 结尾的子数组来生成 j!在这里我假设 j 也可以是负数。!现在可以很容易地推导出 sum+ 一个负数 i-1 th 位置的最大值 j 并将其与 i th 元素连接起来,这让我觉得这是一种贪婪的选择(只是因为最大值 + 元素给了我一个最大值)。

注意:我现在还没有研究过贪心算法,但我知道什么是贪心选择!

编辑:有人说我的算法没有任何意义,所以我试图发布我的代码以使自己清楚。我没有把 j 当作 -ve,因为它们没有成果。 我再说一遍,我的状态被定义为是否可以使用以 i 结尾的子数组来生成 j。

#include<bits/stdc++.h>
using namespace std;
int DP[101][101];
int main()
{
    int i,j,ans=INT_MIN;
    int A[]={3,-1,2,-1,5,-3};
    int N=sizeof(A)/sizeof(int);
    for(i=1;i<=N;i++)
    {
        if(A[i-1]>=0)
            DP[i][A[i-1]]++;
        for(j=0;j<=100;j++)
        {
            if(DP[i-1][j])
            {
                if(j+A[i-1]>=0)
                    DP[i][j+A[i-1]]++;
            }
            if(DP[i][j])
                ans=max(ans,j);
        }
    }
    cout<<ans<<"\n";
    return 0;
}

输出 8

【问题讨论】:

  • 为了清楚起见,我添加了我的代码!
  • 动态编程是一种技术,它不是一种属性。您可以在任何地方使用动态编程来降低时间复杂度,而贪婪是一种属性。你可以说 Dijkstra 的算法是使用动态规划,当它将所有先前计算的距离存储在一个数组中,并使用它们来计算到下一个城市的最短距离。但是,与此同时,Dijkstra 的算法是贪心的。
  • 我的问题不清楚吗?如果是,我很抱歉。我问kadane的算法也是贪心算法还是这个DP的优化形式?我这么说是因为如果我们只考虑我的解决方案中的最高 j,它将产生 kadane 的算法(并且也忽略负 j),其中 j 是可以使用子数组形成的总和。!由于属性最大总和 + 一些 > 较小的总和 + 相同的东西!我明白了你所说的@PhamTrung。
  • IMO,这不是贪婪,实际上是蛮力。 DP只是确保你不需要解决一个case两次,但基本上你还是需要检查所有case,每个状态dp[i][j]一个一个填写。
  • 通常,DP用于递归算法。你的 alg 和 Kadane 的都不是递归的.....

标签: algorithm dynamic-programming greedy


【解决方案1】:

Kadane 是一种迭代动态规划算法。

优化迭代 DP 算法以沿算法进展的主轴移除 DP 矩阵的一维是很常见的。

例如,通常的“最长公共子序列”算法通常用 2D 矩阵来描述,但如果算法从左到右进行,那么你真的只需要 2 列的空间。

Kadane 的算法是应用于一维问题的类似优化,因此整个 DP 数组消失了。由于某种原因,您问题中的 DP 代码具有二维矩阵。我不知道为什么——这真的没有意义。

这个网站很好地解释了推导:https://hackernoon.com/kadanes-algorithm-explained-50316f4fd8a6

【讨论】:

    【解决方案2】:

    我认为这是一个贪心算法,因为 kadanes 算法在每一步找到最大和,然后找到整体解决方案。

    【讨论】:

      【解决方案3】:

      算法简介中所定义,“贪心算法总是做出目前看起来最好的选择。也就是说,它会做出局部最优选择,希望这个选择会导致全局最优解。”

      Kadane 的算法确实通过current_sum = max(0, current_sum + x) 寻找局部最优解;同时,这也可以看作是一种空间优化的动态规划方案——dp[i] 只依赖于dp[i-1],因此我们使用整数变量来节省空间。

      所以我觉得DP的过渡函数恰好有一种贪婪的方式,这使它看起来既像DP又像贪婪。

      【讨论】:

        【解决方案4】:

        Kadane 的算法既可以被视为贪心算法,也可以被视为 DP。正如我们所看到的,我们正在保持整数的运行总和,当它小于 0 时,我们将其重置为 0(贪婪部分)。这是因为继续负总和比重新开始新范围更糟糕。现在它也可以被视为一个 DP,在每个阶段我们有 2 个选择:要么获取当前元素并继续之前的总和,要么重新开始一个新的范围。这两个选择都在实施过程中得到考虑。

        贪婪的索尔

        # Python program to find maximum contiguous subarray
          
        # Function to find the maximum contiguous subarray
        from sys import maxint
        def maxSubArraySum(a,size):
              
            max_so_far = -maxint - 1
            max_ending_here = 0
              
            for i in range(0, size):
                max_ending_here = max_ending_here + a[i]
                if (max_so_far < max_ending_here):
                    max_so_far = max_ending_here
         
                if max_ending_here < 0:
                    max_ending_here = 0  
            return max_so_far
          
        # Driver function to check the above function
        a = [-13, -3, -25, -20, -3, -16, -23, -12, -5, -22, -15, -4, -7]
        print "Maximum contiguous sum is", maxSubArraySum(a,len(a))
        

        DP 溶胶

        # Python program to print largest contiguous array sum
         
        from sys import maxsize
         
        # Function to find the maximum contiguous subarray
        # and print its starting and end index
        def maxSubArraySum(a,size):
         
            max_so_far = -maxsize - 1
            max_ending_here = 0
            start = 0
            end = 0
            s = 0
         
            for i in range(0,size):
         
                max_ending_here += a[i]
         
                if max_so_far < max_ending_here:
                    max_so_far = max_ending_here
                    start = s
                    end = i
         
                if max_ending_here < 0:
                    max_ending_here = 0
                    s = i+1
         
            print ("Maximum contiguous sum is %d"%(max_so_far))
            print ("Starting Index %d"%(start))
            print ("Ending Index %d"%(end))
         
        # Driver program to test maxSubArraySum
        a = [-2, -3, 4, -1, -2, 1, 5, -3]
        maxSubArraySum(a,len(a))
        

        【讨论】:

          【解决方案5】:

          我认为很难说这个算法到底是什么。
          但是本书的大部分内容将此算法归类为 DP 部分,因为您将 dp[n-1] 的解组合成 dp[n] 的解。

          注意:我不明白你为什么使用O(n^2)这个版本的算法 您可以将此算法简化为O(n)

          curmax=0
          sol=0
          for x in array
              curmax+=a[x]
              if(curmax<0)curmax=0
              if(curmax>sol)sol=curmax
          

          【讨论】:

          • 不是 O(N^2) 。它是 O(N* 在任何情况下的最大总和)
          • 哦,是的,我的错.. 但是O(N* maximum sum in any case) 通常大于O(N^2)
          猜你喜欢
          • 1970-01-01
          • 2016-04-17
          • 1970-01-01
          • 2012-12-11
          • 2014-02-17
          • 1970-01-01
          • 1970-01-01
          • 2023-04-02
          • 1970-01-01
          相关资源
          最近更新 更多