算法分析與設計課程作業第二週#1

算法分析與設計課程作業第二週#1

上一週學了分而治之的算法策略,這周就先找了一題貼了此標籤的題試試手。

題目:Maximum Subarray

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
the contiguous subarray [4,-1,2,1] has the largest sum = 6.

思路

這題目描述還挺簡潔的,但一開始我卻想不到從何處下手,回想課上的例子,許多都是將問題不停對半分(例如歸併排序,兩個數乘法),而這個問題直接將數組對半分明顯行不通。後來,就想嘗試下分成幾個連續序列,每個連續序列的和局部最大(就是無論往前加還是往後加都只會變得更小),最後比較這幾個連續序列的和(其實我的代碼是在過程中比較的),從而得到結果。
但怎麼分才能得到一個和局部最大的序列呢?我的想法是:局部和最大的連續序列,要滿足使這個序列無論往前加,還是往後加,和都會變小,滿足這些條件的序列中,序列和最大的序列即是所求。所以可以遍歷數組,用兩個變量,一個sum記錄從某個值開始的連續序列的和,其一開始從整個序列的第一個值開始,一旦sum小於0,就表示前面已經計算的序列的和若再加到後面的序列和上,序列和只會更小,所以就捨棄前面的序列和,從使sum爲0的序列值的下一個值開始計算sum,另一個maxsum記錄到此爲止的連續子數組的最大和(也是其中某個連續序列的和),通過比較maxsum和sum,一旦得到一個更大的和值,就設置該變量。總之,sum在計算中就是其中某個連續子序列的和,maxsum就是計算中最大的sum值,這樣maxsum即是該數組中的一個連續子數組的最大和。

代碼塊

第一次錯誤(沒考慮到數組一開始可以爲負值):

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int sum = 0, maxsum = 0;
        for(int i = 0; i < nums.size(); i++){
            sum += nums[i];
            maxsum = maxsum > sum? maxsum : sum;
            if(sum < 0) sum = 0;
        }
        return maxsum;
    }
};

maxsum一開始不應設置爲0,應設置爲一個無論如何都小於等於後面計算的sum的數,以免後面計算的maxsum是一個不存在的初始值,所以可以設置爲序列的第一個元素的值。
正確版本:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int sum = 0, maxsum = nums[0];
        for(int i = 0; i < nums.size(); i++){
            sum += nums[i];
            maxsum = maxsum > sum? maxsum : sum;
            if(sum < 0) sum = 0;
        }
        return maxsum;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章