这星期学习了分治法,所以在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.
一开始起来,就想用最暴力最直接的方法解,于是有了以下代码:
int maxSubArray(vector<int>& nums) {
int maxsum = nums[0];
for (int i = 1; i <= nums.size(); i++) {
for (int j = 0; j < nums.size()-i+1; j++) {
int t = 0;
for (int k = 0; k < i; k++) {
t += nums[j+k];
}
if (t > maxsum) {
maxsum = t;
cout << maxsum << " ";
}
}
}
return maxsum;
}
测试了几个简单样例,对了~然而提交上去果然超时了,时间复杂度为O(n^3),果然要重新考虑算法。
所以想着尝试用分治法做一下~
看着这道题,完全想不出分治法怎么处理,所以翻了书里的内容再看一下,分成几部分小问题,再分,再分……
于是想着如果把数字分成两部分,最大和子序列可能在左边,也可能在右边,或者是左边和右边的一部分加起来,然后分成的两串小数组再继续按相同的方法递归下去……算法复杂度为O(Nlogn)
class Solution {
public:
int maxSum(vector<int> & nums, int l, int r) {
if (l == r) return nums[l];
int mid = (l + r) / 2;
int maxLeft = maxSum(nums, l, mid);
int maxRight = maxSum(nums, mid + 1, r);
int tL = 0, tR = 0;
int maxL = INT_MIN, maxR = INT_MIN;
for (int i = mid; i >= l; i--) {
tL += nums[i];
if (tL > maxL) maxL = tL;
}
for (int i = mid + 1; i <= r; i++) {
tR += nums[i];
if (tR > maxR) maxR = tR;
}
return maxLeft > maxRight ? (maxLeft > (maxL + maxR) ? maxLeft : (maxL + maxR)) : (maxRight > (maxL + maxR) ? maxRight : (maxL + maxR));
}
int maxSubArray(vector<int>& nums) {
return maxSum(nums, 0, nums.size() - 1);
}
};
未完待续……