劍指Offer-30.連續子數組的最大和(C++/Java)

題目:

HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同窗。今天測試組開完會後,他又發話了:在古老的一維模式識別中,經常須要計算連續子向量的最大和,當向量全爲正數的時候,問題很好解決。可是,若是向量中包含負數,是否應該包含某個負數,並指望旁邊的正數會彌補它呢?例如:{6,-3,-2,7,-15,1,2,2},連續子向量的最大和爲8(從第0個開始,到第3個爲止)。給一個數組,返回它的最大連續子序列的和,你會不會被他忽悠住?(子向量的長度至少是1)數組

分析:

實際上就是求最大的連續子序列和。測試

咱們維護一個臨時序列和,遍歷數組,計算臨時序列和,若是臨時序列和大於最大值,就更新最大值,當臨時序列和小於0時,也就證實此時的序列沒有增加的空間了,將臨時序列和更新爲0,從新計算後續的序列和,最後返回最大值便可。spa

也能夠使用分治法來求此題。對於一個數組來說,最大的連續子序列和,要麼在中間元素的左邊,要麼在中間元素的右邊,要麼跨過中間元素,根據這點能夠利用分治來求。而跨過中間元素的最大子序列和,它的結果一點是從中間元素向兩側來計算的,咱們能夠從中間元素開始,分別向兩端求解最大的序列和,最後返回兩個子序列和的和,注意中間元素只計算一次。code

程序:

C++blog

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        if(array.size() == 0)
            return 0;
        return helper(array, 0, array.size()-1);
    }
    int helper(vector<int>& nums, int left, int right){
        if(left == right)
            return nums[left];
        int mid = (left + right) / 2;
        int maxResult = max(helper(nums, left, mid), helper(nums, mid+1, right));
        maxResult = max(maxResult, maxCrossMid(nums, mid, left, right));
        return maxResult;
    }
    int maxCrossMid(vector<int>& nums, int mid, int left, int right){
        int lsum = INT_MIN;
        int tempSum = 0;
        for(int i = mid; i >= left; --i){
            tempSum += nums[i];
            lsum = max(tempSum, lsum);
        }
        tempSum = 0;
        int rsum = INT_MIN;
        for(int i = mid+1; i <= right; ++i){
            tempSum += nums[i];
            rsum = max(tempSum, rsum);
        }
        return (lsum + rsum);
    }
};

Javaio

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        if(array.length == 0)
            return 0;
        int max = array[0];
        int tempSum = 0;
        for(int num:array){
            tempSum += num;
            if(max < tempSum)
                max = tempSum;
            if(tempSum < 0)
                tempSum = 0;
        }
        return max;
    }
}
相關文章
相關標籤/搜索