最大子序列和问题的几种算法
直接贴代码了:
package data.structure.chapter2;
import java.util.Date;
import java.util.Random;
public class MaxSequenceSumTest {
/**
* @param args
*/
public static void main(String[] args) {
int [] array=new int[10000000];
Random r=new Random(100);
for(int i=0;i<array.length;i++){
int k=r.nextInt(20);
if(k%2==0)
array[i]=0-k;
else
array[i]=k;
// System.out.print(array[i]+" ");
}
// System.out.println();
// maxSum1(array);
// maxSum2(array);
// maxSum3(array);
long start=System.currentTimeMillis();
int sum=maxSum4(array,0,array.length-1);
long end=System.currentTimeMillis();
System.out.print("最大子序列的和为:"+sum+"--------花费时间:");
System.out.println((end-start)/1000+"秒"+(end-start)%1000+"毫秒");
maxSum5(array);
}
/**
* f(n)=f(n-1)+f(n-2)
* f(n)=1 n<=1
*/
public static void f(int n){
long [] array=new long[n+1];
array[0]=1;
array[1]=1;
array[2]=2;
for(int i=3;i<n+1;i++){
array[i]=array[i-1]+array[i-2];
}
for(int i=0;i<n+1;i++){
System.out.println("i="+i+"---------- "+array[i]);
}
}
public static int maxSum1(int [] array){
long start=System.currentTimeMillis();
int sum=0;
for(int i=0;i<array.length;i++){
for(int j=i+1;j<array.length;j++){
int s=array[i];
for(int k=i+1;k<=j;k++){
s=s+array[k];
}
if(s>sum) sum=s;
}
}
long end=System.currentTimeMillis();
System.out.print("最大子序列的和为:"+sum+"--------花费时间:");
System.out.println((end-start)/1000+"秒"+(end-start)%1000+"毫秒");
return sum;
}
/**
* 时间减半而已
* @param array
* @return
*/
public static int maxSum2(int [] array){
int sum=0;
long start=System.currentTimeMillis();
for(int i=0;i<array.length;i++){
for(int j=i+1;j<array.length;j++){
if(array[i]<0)
break;
int s=array[i];
for(int k=i+1;k<=j;k++){
s=s+array[k];
}
if(s>sum) sum=s;
}
}
long end=System.currentTimeMillis();
System.out.print("最大子序列的和为:"+sum+"--------花费时间:");
System.out.println((end-start)/1000+"秒"+(end-start)%1000+"毫秒");
return sum;
}
/**
* 少一重循环
* @param array
* @return
*/
public static int maxSum3(int [] array){
long start=System.currentTimeMillis();
int sum=0;
for(int i=0;i<array.length;i++){
int s=array[i];
for(int j=i+1;j<array.length;j++){
s=s+array[j];
if(s>sum) sum=s;
}
}
long end=System.currentTimeMillis();
System.out.print("最大子序列的和为:"+sum+"--------花费时间:");
System.out.println((end-start)/1000+"秒"+(end-start)%1000+"毫秒");
return sum;
}
/**
* O(NlogN)时间复杂度
* 分治策略:
* 分:把问题分成两个大致相等的子问题,然后递归地对他们求解
* 治:将两个子问题的解修补到一起并可能再做些少量的附加工作,最后得到整个问题的解
* @param array
* @param left
* @param right
* @return
*/
public static int maxSum4(int [] array,int left,int right){
if (left == right)
if (array[left] > 0)
return array[left];
else
return 0;
int middle=(left+right)/2;
int lMax=maxSum4(array,left,middle);
int rMax=maxSum4(array,middle+1,right);
int a=0;
int aMax=0;
for(int i=middle;i>=left;i--){
a=a+array[i];
if(a>aMax)
aMax=a;
}
int b=0;
int bMax=0;
for(int i=middle+1;i<right;i++){
b=b+array[i];
if(b>bMax)
bMax=b;
}
return Math.max(Math.max(lMax, rMax),aMax+bMax);
}
/**
* 如果a[i]小于零,那么它不可能代表最优序列的起点,因为任何包含a[i]的作为起点的子序列都可以通过
* 用a[i+1]作为起点而得到改进。同理,任何小于零的子序列不可能是最优子序列的前缀。
* @param array
* @return
*/
public static int maxSum5(int []array){
long start=System.currentTimeMillis();
int maxSum=0,thisSum=0;
for(int i=0;i<array.length;i++){
thisSum=thisSum+array[i];
if(thisSum>maxSum){
maxSum=thisSum;
}else if(thisSum<0){
thisSum=0;
}
}
long end=System.currentTimeMillis();
System.out.print("最大子序列的和为:"+maxSum+"--------花费时间:");
System.out.println((end-start)/1000+"秒"+(end-start)%1000+"毫秒");
return maxSum;
}
}