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;
}
};
这道题就这样解决了。总结一下,分治算法的核心就是要分,如何分可以借鉴常规手段,从中得到启发。
如有不足,请各位读者不吝赐教。