最大连续子序列——动态规划或贪心算法

Maximum contiguous subsequence -- dynamic programming or greedy algorithm?

本文关键字:动态规划 贪心算法 连续      更新时间:2023-10-16

给定一个数组vector<int> arr有正负两个条目,最大连续子序列问题要求在数组arr中找到一个和最大的(连续)段。空段的和为零。我使用的算法的c++代码如下:

  int MaxContSum(const vector<int>& arr){
    int i,sum=0,max=0;
    for(i=0;i<arr.size();i++){
      if(arr[i]>=0) {if(sum<0) sum=0;}
      else {if(sum>max) max=sum;}
      sum+=arr[i];
    }
    if(sum>max) max=sum; return max;
  }

这个算法是贪婪算法还是动态规划?看起来它只是一个接一个地扫描条目,并基于arr[i]是正还是负(一个局部可检查的条件)应用不同的策略。那么,为什么这个问题出现在动态规划章节中呢?

这是Kadane解决最大子数组问题的算法。它扫描整个序列,并跟踪在迭代之前找到的最大子数组和,以及正好在这一点结束的最大子数组和。它是如何知道子数组的起始位置的呢?无论何时1)前一个和为负,2)遇到一个正的元素,从正的元素开始,然后从那里继续。用简单归纳法证明了它的有效性。

这个算法不是贪心的,但是可以看作是动态规划。

贪婪算法做出一个局部最优的猜测,并坚持下去(只是不断地继续下去)。相反,在这里,算法可以猜测检查从某个点开始的子序列(其中以正元素结束的和为负),然后丢弃它并尝试从其他点开始的子序列(同样,因为和变为负且元素为正)。

反过来,也可以看作是一个动态规划问题。正如维基百科条目所说:

由于该算法使用最优子结构的方式(在每个位置结束的最大子数组以一种简单的方式从一个相关但较小且重叠的子问题中计算:在前一个位置结束的最大子数组),该算法可以被视为动态规划的一个简单示例。

问题应该具有两个主要属性,以便有资格使用DP解决:

  • 重叠子问题
  • 最优子结构

从你所呈现的,第一个属性肯定是缺失的,因此我不会把这个算法归类为DP。另一方面,您使用较小问题的计算结果来获得最终结果-因此我们有最优子结构,这可能是您在动态规划章节中找到该算法的原因,尽管它不应该属于那里。