java求解最大子列和问题

最大子列和问题

我们通过四种算法分别通过java语言解决最大子列和问题
问题来源:MOOC-浙江大学-数据结构-1.3应用实例(最大子列和问题)
传送门

//最大子列和问题
import java.util.*;
public class Main{
 public static void main(String [] args) {
  Scanner scan =new Scanner(System.in);
  int thissum,maxsum=0;
  int n=scan.nextInt();
  int []a=new int[n];
  for(int i=0;i<n;i++) 
   a[i]=scan.nextInt();
  for(int j=0;j<a.length;j++) {
   for(int k=j;k<a.length;k++){
    thissum=0;
    for(int h=j;h<=k;h++) {
     thissum=thissum+a[h];
     if(thissum>maxsum) {
      maxsum=thissum;
     }
    }
   }
  }
  System.out.println("sum="+maxsum);
 }
}

运行结果:
运行结果

以上算法时间复杂度较大,为(N^ 3)不利于大数据运算,通过观察,我们能发现,以上代码中的第三重循环可删除,故我们采用以下算法,其时间复杂度为(N^2):

package asd;
import java.util.*;
public class gg{
 public static void main(String [] args) {
  Scanner scan =new Scanner(System.in);
  int thissum,maxsum=0;
  int n=scan.nextInt();
  int []a=new int [n];
  for (int i = 0; i < n; i++) {
   a[i]=scan.nextInt();
  }
  for (int i = 0; i <a.length; i++) {
   thissum=0;
   for (int j = i; j < a.length; j++) {
    thissum+=a[j];
    if(thissum>maxsum) {
     maxsum=thissum;
    }
   }
  }
  System.out.println("sum="+maxsum);
 }
}

运行结果:
运行结果
以上算法时间复杂度为(N^2),但是当处理大数据时,仍不使用,所以我们可以再次简化代码,采用分而治之的思想方法,从而可以将时间复杂度减少为:(N*lgN):
分而治之的核心思想是将数组分块治理,首先二分数组,然后分别求解出左侧最大子列和以及右侧最大子列和,再将左侧最大子列和与右侧最大子列和与两者之和进行比较,从而能得出整体最大子列和。

import java.util.*;
public class Main{
 public static void main(String [] args) {
  Scanner scan =new Scanner (System.in);
  int n=scan.nextInt();
  int []a=new int [n];
  for (int i = 0; i < a.length; i++) 
   a[i]=scan.nextInt();
  int max=Sort(a, 0, n-1);
  System.out.println("sum="+max);
 }
public static int Sort(int[] a, int left, int right) {
  // TODO Auto-generated method stub
  int maxleft,maxright;
  if(left==right) {//判断子列是否只有一个元素;
   if(left>0) {
    return a[left];
   }
   else 
    return 0;
  }
  int midnum=(left+right)/2;
  maxleft=Sort(a,left,midnum);
  maxright=Sort(a,midnum+1,right);
  int thisleftnum = 0,thisrightnum=0;//左边的最大子列和
  int maxleftsum = 0, maxrightsum = 0;//左边的和,右边的和
  for(int i=midnum;i>=left;i--) {//左侧最大子列和
   maxleftsum+=a[i];
   if(maxleftsum>thisleftnum) {
    thisleftnum=maxleftsum;
   }
  }
  for(int j=midnum+1;j<=right;j++) {//右侧最大子列和
   maxrightsum+=a[j];
   if(maxrightsum>thisrightnum) {
    thisrightnum=maxrightsum;
   }
  }
  return max(maxleft,maxright,thisleftnum+thisrightnum);
 }
 public static int max(int a, int b, int c) {
  // TODO Auto-generated method stub
  int t;
  if(a>b){t=a;a=b;b=t;}
  /*交换x,y的值*/
  if(a>c){t=c;c=a;a=t;}
  /*交换x,z的值*/
  if(b>c){t=b;b=c;c=t;}
  return c;
 }
}

运行结果:

5
2 3 4 -9 2
sum=9

通过观察,我们发现,这还不是最简单的算法,我们通过“在线处理算法”,所以只需要将数组遍历一遍,得出结果。
从而能够将时间复杂度降为O(N):

package asd;
import java.util.*;
public class gg{
 public static void main(String[] args) {
  Scanner scan=new Scanner(System.in);
  int thissum = 0,maxsum=0;
  int n=scan.nextInt();
  int []a=new int [n];
  for (int i = 0; i < a.length; i++) {
   a[i]=scan.nextInt();
  }
  for (int i = 0; i < a.length; i++) {
   thissum+=a[i];
   if(thissum>maxsum) {
    maxsum=thissum;
   }
   else if(thissum<0) {//当小于0的时候,直接排除
    thissum=0;
   }
  }
  System.out.println("sum="+maxsum);
 }
}

运行结果:

6
2 3 4 5 -2 -3
sum=14

由于必须要将数组遍历一遍,所以时间复杂度最低为O(N),通过以上解法。我们能够得出最为简便的算法:在线处理,从而能够高效率的解决最大子列和问题。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值