/**
* 求一个序列的最大字段和:
* 比如序列{-2,11,-4,13} 则最大字段和为18
* @author biakia
*
*/
public class MaxSubSum {
/*
* 求最大字段和的分治算法:
* 如果将所给的序列a[1:n]分为两段:a[1:n/2],a[n/2+1,b],那么要求最大字段和,共三种情况:
* 1、a[1:n]的最大字段和和a[1:n/2]一样
* 2、a[1:n]的最大字段和和a[n/2+1,n]一样
* 3、a[1:n]的最大字段和跨越了左右两个子序列,所以总的最大字段和是左右最大字段和相加
*/
private static int MSSum(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=MSSum(a,left,center);
//右边最大字段和
int rightsum=MSSum(a,center+1,right);
//跨越左右的最大字段和
int s1=0;
int l_sum=0;
for(int i=center;i>=left;i--){
l_sum+=a[i];
if(l_sum>s1)
s1=l_sum;
}
int s2=0;
int r_sum=0;
for(int i=center+1;i<=right;i++){
r_sum+=a[i];
if(r_sum>s2)
s2=r_sum;
}
sum=s1+s2;
if(sum<leftsum)
sum=leftsum;
if(sum<rightsum)
sum=rightsum;
}
return sum;
}
public static void main(String[] args) {
int[] a={1,2,5,-9,8,7,-4,3};
int s=MSSum(a,0,a.length-1);
System.out.println(s);
}
}
上面的算法是典型的分治算法,时间复杂度为O(nlogn),下面给出最大字段和的动态规划算法,将时间复杂度降到O(n)
/**
* 求一个序列的最大字段和:
* 比如序列{-2,11,-4,13} 则最大字段和为18
* @author biakia
*
*/
public class MaxSubSum {
/*
* 最大字段和的动态规划递归式:
* b[j]=max{b[j-1]+a[j],a[j]},1<j<=n
* 其中b[j]是1到j的最大字段和
*/
private static int MaxSum(int n,int[] a){
int sum=0,b=0;
for(int i=0;i<n;i++){
if(b>0)b+=a[i];
else b=a[i];
if(b>sum)sum=b;
}
return sum;
}
public static void main(String[] args) {
int[] a={1,2,5,-9,8,7,-4,3};
int s=MaxSum(a.length,a);
System.out.println(s);
}
}