您的位置:首页 > 其它

leetcode 52:Maximum Subarray

2015-11-16 20:59 288 查看
题目:

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
.

click to show more practice.

More practice:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

思路:
首先想到的是用动态规划来做,因为动态规划跟前面计算的结果有关。

所以,对于给定的数组nums,我们可以定义一个相同大小的数组DP来存储当前元素对应的最大的连续元素之和。

以[−2,1,−3,4,−1,2,1,−5,4]举例分析。

当i=0时,DP[i]=-2;

当i=1时,DP[i]=1;

当i=2时,DP[i]=-2;

当i=3时,DP[i]=4;

......

很容易得出DP的递推式如下:

DP[i]=max(DP[i-1]+nums[i],nums[i]);

DP中最大值即为最后的返回值。

时间复杂度:O(n);

实现如下:

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

};

下面针对more practice,用分而治之的方法求解(参考:算法导论):
分治策略是将数组分成两个规模尽可能相等的子数组,然后求解两个子数组。

但是最大子数组有可能出现在以下几种情况中:

完全位于子数组nums[low...mid]中;

完全位于子数组nums[mid...high]中;

跨越了中点;

因此我们需在上面三种情况中找最大者。

时间复杂度:O(nlgn)

实现如下:

class Solution {
public:
int maxSubArray(vector<int>& nums) {
int size = nums.size();
if (size == 1) return nums[0];
return FindMaximumSubArray(nums,0,size-1);
}
private:
int FindMaxCrossingSubArray(vector<int>& nums, int low, int mid, int high)
{
int leftSum = -0XFFFF, rightSum = -0XFFFF, tempSum = 0;
for (int i = mid; i >= low; i--)
{
tempSum += nums[i];
if (tempSum > leftSum) leftSum = tempSum;
}
tempSum = 0;
for (int i = mid + 1; i <= high; i++)
{
tempSum += nums[i];
if (tempSum > rightSum) rightSum = tempSum;
}
return leftSum + rightSum;
}

int FindMaximumSubArray(vector<int>& nums, int low, int high)
{
if (high == low) return nums[low];
int mid = (low + high) / 2;
int leftSum = FindMaximumSubArray(nums,low,mid);
int rightSum = FindMaximumSubArray(nums, mid+1, high);
int crossSum = FindMaxCrossingSubArray(nums, low, mid, high);
return max(max(leftSum, rightSum), crossSum);
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: