算法分析之最大子段求和

给定由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;
}

猜你喜欢

转载自www.cnblogs.com/khnl/p/11639292.html