【问题描述】
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
.
【问题分析】
题意:先来理解一下题意,给定一个数组,找出一个连续的子数组,使得子数组之和是最大值。
方法一:令max = nums[0],sum = 0。遍历nums,nums[i]与sum相加,如果sum大于max,用sum替换max的值;如果sum小于0了,重置sum为0,最后返回max,时间复杂度为遍历一遍数组O(N
)。
方法二:分治方法:
我们首先定义几个参数:
sum——一个数组的和;
leftmx——从数组最左开始最大的和;
rightmx——从数组最右开始最大的和;
mx——数组最大的和。
将一个数组A从中间分开,变成两个子数组A1和A2,leftmx1,rightmx1,mx1,sum1表示子数组A1的参数,leftmx2,rightmx2,mx2,sum2表示子数组A2的参数。
有以下关系:
mx = max(max(mx1, mx2), rightmx1 + leftmx2);
leftmx = max(leftmx1, sum1 + leftmx2);
rightmx = max(rightmx2, sum2 + rightmx1);
sum = sum1 + sum2。
对子数组也进行上面的分治操作,直到数组变成不可拆分的单元,即left等于right,此时leftmx = rightmx = mx = sum = nums[left]。
最后返回mx。T(n) = 2T(n/2) + O(1),时间复杂度为O(N)。
【源代码】
方法一:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int max = nums[0];
int sum = 0;
int i = 0;
while (i < nums.size()) {
sum += nums[i];
if (sum > max) {
max = sum;
}
if (sum < 0) {
sum = 0;
}
i++;
}
return max;
}
};
/**
sum-------the total sum of the subarray.
leftmx----largest sum starting from the left most element.
rightmx---largest sum starting ending the right most element.
mx--------largest sum of the subarray.
**/
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if (nums.size() == 0) {
return 0;
}
if (nums.size() == 1) {
return nums[0];
}
int mx,leftmx,rightmx,sum = 0;
maxSubArray(nums, 0, nums.size()-1, mx, leftmx, rightmx, sum);
return mx;
}
private:
void maxSubArray(vector<int>& nums, int left, int right, int& mx, int& leftmx, int& rightmx, int& sum) {
if (left == right) {
mx = leftmx = rightmx = sum = nums[left];
} else {
int leftmx1, sum1, rightmx1, mx1 = 0;
int leftmx2, sum2, rightmx2, mx2 = 0;
int mid = (left + right) / 2;
maxSubArray(nums, left, mid, mx1, leftmx1, rightmx1, sum1);
maxSubArray(nums, mid+1, right, mx2, leftmx2, rightmx2, sum2);
mx = max(max(mx1, mx2), rightmx1 + leftmx2);
leftmx = max(leftmx1, sum1 + leftmx2);
rightmx = max(rightmx2, sum2 + rightmx1);
sum = sum1 + sum2;
}
}
};