算法分析之最大子段求和

Posted khnl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法分析之最大子段求和相关的知识,希望对你有一定的参考价值。

给定由n个整数(包含负整数)组成的序列a1,a2,...,an,求该序列子段和的最大值。
当所有整数均为负值时定义其最大子段和为0。
所求的最优值为:
技术图片

 

 


例如,当(a1,a2, ……a7,a8)=(1,-3, 7,8,-4,12, -10,6)时, 最大子段和为:

技术图片

 

 

 

 

分治方法求解
从问题的解的结构可以看出,它适合于用分治策略求解:
如果将所给的序列a[1:n]分为长度相等的两段a[1:n/2]和a[n/2+1:n],分别求出这两段的最大子段和,则a[1:n]的最大子段和有三种情形:
a[1:n]的最大子段和与a[1:n/2]的最大子段和相同;
a[1:n]的最大子段和与a[n/2+1:n]的最大子段和相同;
a[1:n]的最大子段和为下面的形式。
技术图片

 

 



A、B这两种情形可递归求得。
对于情形C,容易看出,a[n/2]与a[n/2+1]在最优子序列中。因此,我们可以在a[1:n/2]和a[n/2+1:n]中分别计算出s1和s2。则s1+s2即为出现情形C使得最优值。
{1,-3,7,8,-4,12,-10,6}

C 等价于求从某个元素开始的子段和的最大值
例如:求从数组0开始的子段和的最大值

sum=0,max=0;
for(int i=0;i<=n;i++){
	sum=sum+a[i];
	if(sum>max)
		max=sum;
}

 以下是整体代码:

int MaxSubSum(int a, int left, int right){
  int sum=0;
  if (left==right)sum=a[left]>0?a[left]:0;
  else{int center=(left+right)/2;
    int leftsum=MaxSubSum(a,left,center);
    int rightsum=MaxSubSum(a,center+1,right);
    int s1=0;lefts=0;
    for (int i=center;i>=left;i--){
	lefts+=a[i];
       if (lefts>s1) s1=lefts;
    }
    int s2=0;rights=0;
    for (int i=center+1;i<=right;i++){
      rights+=a[i];
      if (rights>s2) s2=rights;
    }
    sum=s1+s2;
    if (sum<leftsum) sum=leftsum;
    if (sum<sightsum) sum=rightsum;
  }
  return sum;
}

 

以上是关于算法分析之最大子段求和的主要内容,如果未能解决你的问题,请参考以下文章

算法设计与分析--求最大子段和问题(蛮力法分治法动态规划法) C++实现

『嗨威说』算法设计与分析 - PTA 数字三角形 / 最大子段和 / 编辑距离问题(第三章上机实践报告)

最大子段和

最大子段和之环形问题

算法笔记--最大子段和问题

分治算法 ------最大子段和