分治演算法解題: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;
}
};
這道題就這樣解決了。總結一下,分治演算法的核心就是要分,如何分可以借鑑常規手段,從中得到啟發。
如有不足,請各位讀者不吝賜教。