五种方求最大子序列和

方法介绍

方法一:三重循环。

方法二:二重循环

方法三:分治。对原序列,取中间为分界点,分成左右两半,最大子序列S恰有三种情况:完全落在左半部分(可递归求解), 完全落在右半部分(可递归求解),跨两半。对于跨两半的情况,把最大子序列分成左右两段L和R, 注意左段L一定是以分界点为终点的最大子序列(否则若L’>L则S’=L’+R>L+R=S矛盾),即可以从分界点开始向左扫描一遍求出L。

方法四:动态规划。对于以i为终点(包括i)的最大子序列S,恰有三种情况: S长0,依定义和为0,因max初始0, 可以不考虑;S长1;S长>=2,此时一定是以i-1为终点的最大子序列再添加元素i。

方法五:求最大子序列,就是找两点,使起点和终点间积分最大;在积分序列中看,就是使 (终点值-起点值)最大。 给定终点,起点应为终点前的最小值。从头到尾扫描积分序列,O(1)更新迄今为止最小值thisMin, 当前值-thisMin即以当前点为终点的最大子序列。也可给定起点,终点应为起点后的最大值,程序改为从后向前扫描。

代码实现

package testtt;

public class Tee {
//方法一
	 public static int maxSum1(int [] a){
	    	int maxSum=0;
	    	for(int i=0;i<a.length;i++)
	    		for(int j=i;j<a.length;j++){
	    			int thisSum=0;
	    			for(int k=i;k<=j;k++){
	    				thisSum+=a[k];
	    			}
	    			if(thisSum>maxSum){
	    				maxSum=thisSum;
	    			}
	    		}
	    	return maxSum;
	    }
	 
	//方法二,该算法运行时间为O(n^2)
	    public static int maxSum2(int [] a){
	    	int maxSum=0;
	    	for(int i=0;i<a.length;i++){
	    		int thisSum=0;
	    		for(int j=i;j<a.length;j++){
	    			
	    			thisSum+=a[j];
	    			if(thisSum>maxSum){
	    				maxSum=thisSum;
	    			}
	    		}
	    	}
	    	return maxSum;
	    }
	    
	    //方法三,该算法时间复杂度为O(NlogN)
	    public static int max3(int a,int b,int c){
	    	int maxnumber=Math.max(a, b);
	    	return Math.max(c, maxnumber);
	    }
	    public static int maxSum3(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 maxSumLeft=maxSum3(a,left,center);//求出左半部分的最大子序列和
	    	int maxSumRight=maxSum3(a,center+1,right);//求出右半部分最大子序列的和
	    	
	    	int maxBorderLeft=0;int leftBorder=0;//包含左半部分最后一个数的最大值求解
	    	for(int i=center;i>=left;i--){
	    		leftBorder+=a[i];
	    		if(leftBorder>maxBorderLeft){
	    			maxBorderLeft=leftBorder;
	    		}
	    	}
	    	
	    	int maxBorderRight=0;int rightBorder=0;//包含右半部分第一个数的最大值求解
	    	for(int i=center+1;i<=right;i++){
	    		rightBorder+=a[i];
	    		if(rightBorder>maxBorderRight){
	    			maxBorderRight=rightBorder;
	    		}
	    	}
	    	return max3(maxSumLeft,maxSumRight,maxBorderLeft+maxBorderRight);
	    }
	    
	    //方法四,联机算法  该算法时间复杂度为O(n)
	    public static int maxSum4(int [] a){
	    	int maxSum=0;int thisSum=0;
	    	for(int i=0;i<a.length;i++){
	    		thisSum+=a[i];
	    		if(thisSum>maxSum){
	    			maxSum=thisSum;
	    		}else if(thisSum<0){
	    			thisSum=0;
	    		}
	    	}
	    	return maxSum;
	    }
	    
      //方法五
	    public static  double f5( double [] a, int  mOff, int  mLen ) {
	    	int n = a.length;
	    	double cum[] = new double[n];
	    	if( n > 0 )
	    		cum[0] = a[0];
	    	for( int i=1; i<n; i++ )
	    		cum[i] = cum[i-1] + a[i]; // cum[i] means cummulate [0,i]

	    	double max = 0;
	    	double thisMin = 0;
	    	int off = -1;
	    	for( int i=0; i<n; i++ ) {
	    		if( cum[i] < thisMin ) { // min cum[0,i]
	    			thisMin = cum[i];
	    			off = i;
	    		}
	    		double thisMax = cum[i] - thisMin; // max [,i]
	    		if( thisMax > max ) {
	    			max = thisMax;
	    			// (off, i]
	    			mOff = off + 1;
	    			mLen = i - off;
	    		}
	    	}
	    	return max;
	    }
	    
	    
		static int [] a={-1,-2,5,6,3,-1,10};
		static double [] b={-1,-2,5,6,3,-1,10};
		public static void main(String args[]){
			int firstsum=maxSum1(a);
			int secondsum=maxSum2(a);
			int thirdsum=maxSum3(a,0,a.length-1);
			int forthsum=maxSum4(a);
			double fifthsum = f5(b,3,3);
			System.out.print(firstsum+"\n"+secondsum+"\n"+thirdsum+"\n"+forthsum+"\n"+fifthsum);
		}