问题描述:给定n个整数组成的序列,求其中子段和的最大值。当所有整数均为非负整数时定义其最大子段和为0
方法一:O(n²)用一个值存储最大和,用枚举所有和的方法,来与这个值比较并更新最大值。
1 int MaxSum(int n, int *a, int &besti, int &bestj) 2 { 3 int sum=0; 4 for(int i=0;i<n;++i) 5 { 6 int parts=0; 7 for(int j=i;j<n;++j) 8 { 9 parts+=a[i]; 10 if(parts>sum){ 11 sum=parts; 12 besti=i; 13 bestj=j; 14 } 15 } 16 } 17 return sum; 18 }
方法二:O(nlogn)分治,分别求两边的最大子段和,再从中间分开的位置向两边拓展求最大和,三个值比较得最大子段和
1 int MaxSubSum(int *a,int left,int right) 2 { 3 int sum=0; 4 if(left==right) sum=a[left]>0?a[left]:0; 5 else{ 6 int c=(right+left)/2; 7 int lsum=MaxSubSum(a,left,c); 8 int rsum=MaxSubSum(a,c+1,right); 9 int s1=0,lefts=0; 10 for(int i=c;i>=left;--i)//左 11 { 12 lefts+=a[i]; 13 if(lefts>s1) s1=lefts; 14 } 15 int s2=0,rights=0; 16 for(int i=c;i<=rights;--i)//右 17 { 18 rights+=a[i]; 19 if(rights>s1) s1=rights; 20 } 21 sum=s1+s2; 22 if(lsum>sum) sum=lsum; 23 if(rsum>sum) sum=rsum; 24 } 25 return sum; 26 } 27 int MaxSum(int n, int *a) 28 { 29 return MaxSubSum(a,0,n-1); 30 }
方法三:O(n)动态规划,求到这一位时能达到得最大子段和
1 int MaxSum(int n,int *a) 2 { 3 int sum=0,parts=0; 4 for(int i=0;i<n;++i) 5 { 6 if(parts>0) parts+=a[i]; 7 else parts=a[i]; 8 if(parts>sum) sum=parts; 9 } 10 return sum; 11 }