码迷,mamicode.com
首页 > 编程语言 > 详细

算法分析之最大子段求和

时间:2019-10-09 09:43:06      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:bsp   等价   turn   方法   序列   play   style   splay   family   

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

 

算法分析之最大子段求和

标签:bsp   等价   turn   方法   序列   play   style   splay   family   

原文地址:https://www.cnblogs.com/khnl/p/11639292.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!