最大子序列求和的问题就是对于给定的整数数列(里面可能有负数)A1,A2,…AN,求Ai到Ak的和的最大值。
例如 -2,11,-4,13,-5,-2 这个数列的最大子序列和就是11-4+13=20。下面用四种方法实现这个功能。时间复杂度依次减小。
- 用三个for循环
public class MaxSubSum {
public static void main(String[] args) {
int a[]={-2,11,-4,13,-5,-2};
int maxsum=0,i,j,k;
for(i=0;i<a.length;i++){
for(j=i;j<a.length;j++){
int thissum=0;
for(k=i;k<=j;k++){
thissum=thissum+a[k];
if(thissum>maxsum){
maxsum=thissum;
}
}
}
}
System.out.println(maxsum);
}
}
很显然这个的时间复杂度是O(N3)
- 用两个for循环,上面的第三个for是可以不用的
public class MaxSubSum2 {
public static void main(String[] args) {
int a[]={-2,11,-4,13,-5,-2};
int maxsum=0,i,j;
for(i=0;i<a.length;i++){
int thissum=0;
for(j=i;j<a.length;j++){
thissum=thissum+a[j];
if(thissum>maxsum){
maxsum=thissum;
}
}
}
System.out.println(maxsum);
}
}
少了一个for,时间复杂度为O(N2)
- 用递归,程序较多一点
public class MaxSubSum3 {
public int maxsum(int a[],int left,int right){
if(left==right){ //基准情况
if(a[left]>0){
return a[left];
}
else
{
return 0;
}
}
int center=(left+right)/2;
int maxleftsum=maxsum(a,left,center); //左边递归
int maxrightsum=maxsum(a,center+1,right); //右边递归
int maxleftbodersum=0,leftbodersum=0;
for(int i=center;i>=left;i--){
leftbodersum=leftbodersum+a[i];
if(leftbodersum>maxleftbodersum){
maxleftbodersum=leftbodersum;
}
}
int maxrightbodersum=0,rightbodersum=0;
for(int i=center+1;i<=right;i++){
rightbodersum=rightbodersum+a[i];
if(rightbodersum>maxrightbodersum){
maxrightbodersum=rightbodersum;
}
}
return max(maxleftsum,maxrightsum,maxleftbodersum+maxrightbodersum);
}
private int max(int x, int y, int z) {
int temp,result;
if(x>y){
temp=x;
}
else{
temp=y;
}
if(temp>z){
result=temp;
}
else{
result=z;
}
return result;
}
/**
* @param args
*/
public static void main(String[] args) {
int a[]={-2,11,-4,13,-5,-2};
MaxSubSum3 max=new MaxSubSum3();
max.maxsum(a, 0, a.length-1);
System.out.println(max.maxsum(a, 0, a.length-1));
}
}
这两个for是找出含有中间项的和的最大值。这个算法递归的是每次变成N/2,然后for循环的时间复杂度为O(N),整个算法的时间复杂度是O(NlogN)。
- 最后一个也是最优的算法了吧 ,因为不需要知道这个子序列在哪里,只需要知道最后的值,子序列中第一项如果是负数那么肯定不能是最大的了。
public class MaxSubSum4
{
public static void main(String[] args) {
int a[]={-2,11,-4,13,-5,-2};
int maxsum=0,thissum=0;
for(int i=0;i<a.length;i++){
thissum=thissum+a[i];
if(thissum>maxsum){
maxsum=thissum;
}
else if(thissum<0){
thissum=0;
}
}
System.out.println(maxsum);
}
}
这个只有一个for循环,所以时间复杂度为O(N)。