最大子序列和问题的四种求解以及他们的时间复杂度

最大子序列求和的问题就是对于给定的整数数列(里面可能有负数)A1,A2,…AN,求Ai到Ak的和的最大值。
例如 -2,11,-4,13,-5,-2 这个数列的最大子序列和就是11-4+13=20。下面用四种方法实现这个功能。时间复杂度依次减小。

  1. 用三个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

  1. 用两个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

  1. 用递归,程序较多一点


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)。

  1. 最后一个也是最优的算法了吧 ,因为不需要知道这个子序列在哪里,只需要知道最后的值,子序列中第一项如果是负数那么肯定不能是最大的了。


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)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值