1. 程式人生 > >求陣列的連續子陣列之和的最大值

求陣列的連續子陣列之和的最大值

同一個問題:http://blog.csdn.net/witsmakemen/article/details/17740933  

 一個有N個整數元素的一維陣列{A[0],A[1],....,A[N-1],A[N]},這個陣列有很多連續的子陣列,那麼連續子陣列之和的最大的一個的值是什麼?

   先給出一個時間複雜度為O(N^2)的求解程式實現,思想很簡單,就是遍歷陣列中所有的子陣列,程式碼如下:

/**
 * 計算陣列的最大子序列
 * @author win7
 *
 */
public class MaxSubArraySum {
	
	public static int sumN2(int [] array){
		int sum=0,maxSum=Integer.MIN_VALUE;
		int n=array.length;
		int count=0;
		for(int i=0;i<n;i++){
			sum=0;
			for(int j=i;j<n;j++){
				sum+=array[j];
				if(sum>maxSum){
					maxSum=sum;
				}
				count++;
			}
		}
		System.out.println("length="+n+"||count="+count);
		return maxSum;
	}
	public static void main(String [] args){
//		System.out.println("MIN_VALUE="+Integer.MIN_VALUE);
		int [] array={-5,-2,-3,-5,-3,-2};
		int sum=MaxSubArraySum.sumN2(array);
		System.out.println("最大子序列和="+sum);
	}

}

因為子陣列求和滿足動態規劃的後無效特性,所以可以使用動態規劃的思想,從分治的演算法中得到提示:可以考慮陣列的第一個元素A[0],以及最大的一段陣列(A[i],...A[j])跟A[0]之間的關係,有一下幾種情況:

1.當0=i=j時,元素A[0]元素本身構成和最大的一段;

2.當0=i<j時,和最大的一段以A[0]開始;

3.當0<i時,元素A[0]跟和最大的一段沒有關係。

從上面的三種情況可以將一個大問題(N個元素的陣列)轉化為一個較小的問題(n-1個元素的陣列)。假設知道(A[1],...,A[N-1])中包含A[1]的和最大的一段的和為start[1]。那麼,根據上面分析的三種情況,不難看出(A[0],...,A[N-1])中問題的解all[0]是三種情況的最大值max{A[0],A[0]+start[1],all[1]}。通過問題分析,可以看到問題滿足無後效性,可以使用動態規劃的方法來解決。

程式程式碼實現如下:

    /**
     * 在時間複雜度為O(N)內找出陣列中最大的子序列的累加和
     * @param array
     * @return
     */
    public static int sumN(int [] array){
    	int n=array.length;
    	int all=array[n-1],start=array[n-1];
    	int count=0;
    	for(int i=n-2;i>=0;i--){
    		if((start+array[i])>array[i]){
    			start=start+array[i];
    		}else{
    			start=array[i];
    		}
    		if(all<start){
    			all=start;
    		}
    		count++;
    	}
        System.out.println("陣列長度="+array.length+"||時間複雜度="+count);  
    	return all;
    }