最大子序列和

/**
 * 求最大子序列和的問題
 * 給定(可能有負數)一組整數值,求這組子序列的最大值
 * @author breeze
 *
 */
public class MaxSubSum {
    //時間複雜度爲N^2
    public static int maxSubSum2(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;
    }
    
    //求最大子序列和的最優解(最簡潔版,但很差理解,下面那個解釋版好理解)
    public static int maxSubSum4(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;
    }
    //最大子序列和的最優解的解釋版
    /**
     * currSum是以當前元素爲結尾的連續子數組之和,maxSum是全局的最大子數組之和
     * 事實上,當從前日後掃描一個數組時,對於第i個元素,有兩種選擇,要麼放入前面已經找到的子數組,要麼不放入,而是做爲新的子數組的第一個元素
     * 若是currSum>0,則令currSum加上a[i];
     * 若是currSum<0,則置currSum等於當前元素,即currSum = a[i]
     * 這就至關於,若是currSum(i)是以i結尾的最大連續子數組的和,那麼currSum(i) = max{0,currSum(i-1)+a[i]}
     * 若是maxSum<currSum,則更新maxSum=currSum;不然maxSum保持原值,不更新
     * 舉個例子:{1,-2,3,10,-4,7,2,-5}
     * currSum:0->1->-1->3->13->9->16->18->13
     * maxSum: 0->1-> 1->3->13->13->16->18->18
     * @param a
     * @return
     */
    public static int maxSubSum(int[] a){
        int maxSum = a[0];//數組全爲負數的狀況下,返回最大數
        int currSum = 0;
        for(int i = 0;i<a.length;i++){
            if(currSum >= 0){
                currSum += a[i];
            }else{
                currSum = a[i];
            }
            
            if(maxSum < currSum){
                maxSum = currSum;
            }
        }
        return maxSum;
    }
    /**
     * 延伸一:求出最大連續子數組和,同時要求輸出所求子數組的開始位置和結束位置
     * 
     * @param a
     * @return
     */
    public static int maxSubSumIndex(int[] a){
        int maxSum = a[0];//數組全爲負數的狀況下,返回最大數
        int currSum = 0;
        int start = 0;
        int end = 0;
        for(int i = 0;i<a.length;i++){
            if(currSum >= 0){
                currSum += a[i];
            }else{
                currSum = a[i];
                start = i;
                end = i;//每次重置以當前元素爲結尾的連續子數組之和時,須要更新開始和結束位置。
            }
            
            if(maxSum < currSum){
                maxSum = currSum;
                end = i;//每次全局最大值變更時,須要更新結束位置
            }
        }
        System.out.println("start:"+start+",end:"+end);
        return maxSum;
    }
    
    
    
    public static void main(String[] args) {
        int[] a = {-2,11,-4,13,-5,-2,9};
//        int result = maxSubSum2(a);
        int result = maxSubSumIndex(a);
        System.out.println(result);
    }
}
相關文章
相關標籤/搜索