1. 程式人生 > >分治演算法解題:Maximum Subarray

分治演算法解題:Maximum Subarray

leetcode上的分治演算法有這樣一道題:

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),每次相加之後與事先設定的ans變數比較,若sum小於0則將其置為0,表示捨棄前面的數。以上面示例的陣列為例:


(預設ans = -2)


sum =  -2. ans = -2 -> sum = 0

sum = 1,   ans = 1  -> sum = 1

sum = -2   ans = 1 ->  sum = 0

sum = 4    ans = 4 ->  sum = 4

``````


以此類推即可得出最大的組合,即為ans。return即可。程式碼如下:

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

當然,這是一道分治演算法的題目,自然也有分治演算法的解題方法。

用分治演算法,最大的問題就是“怎麼分”的問題。一開始我想的是找到一個數然後向後分,後來發現這樣並不可行;結合上述做法,決定向前分。也就是說,我找到一個元素,然後討論他前面的數加起來的值,進行比較取捨,然後再加上當前數。仍然以上面的陣列為例:

int num[]       //num[2]表示從第一位元素開始到第三個數字所能加出來的最大的數字

num[0] = -2;                             ans = -2;

num[1] = 0 + 1 = 1;                 ans = 1;

num[2] = 1 + (-3) = -2;            ans = 1;

num[3] = 0 + 4 = 4;                 ans = 4;

``````以此類推即可得到最大的ans。程式碼如下:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int s = nums.size();
        int num[s];
        int maxnum = nums[0];
        num[0] = nums[0];
        for (int i = 1; i < s; i++){
            if (num[i - 1] > 0){
                num[i] = nums[i] + num[i - 1];
            }
            else{
                num[i] = nums[i];
            }
            maxnum = max(num[i], maxnum);
        }
        return maxnum;
    }
};

這道題就這樣解決了。總結一下,分治演算法的核心就是要分,如何分可以借鑑常規手段,從中得到啟發。

如有不足,請各位讀者不吝賜教。