1. 思路A
这个题目是一个很经典的DP(动态规划)问题,我们定义dp[i]表示以i结尾的子序列最大和为多少,那么递推关系就很明确了,对于一个位置X,要么连上前面X+dp[X-1],要么自己单独成为子序列开始X,所以结果就是两者较大值:
d p [ x ] = m a x ( d p [ x − 1 ] , 0 ) + x dp[x]=max(dp[x-1],0)+x dp[x]=max(dp[x−1],0)+x
时间复杂度O(n),空间复杂度O(1)
2. 代码A
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int ret = nums[0];
for(int i = 1; i < nums.size(); ++i)
{
nums[i] = nums[i] + max(0, nums[i-1]);
ret = max(ret, nums[i]);
}
return ret;
}
};
3. 思路B
看题目中提示,题目可以使用分治的方法来做,虽然效率比不上dp但是可以作为一种思路。我们将原数组分为两部分,那么子序列只有可能是以下三种情况:
- 全部在左边部分
- 全部在右边部分
- 一部分在左一部分在右
对于前面两钟情况,我们只需要进行递归即可,那么对于第三种情况,我们可以变成在左边部分找到以最后一个元素结尾的子序列最大和,和在右边部分找到以第一个元素开头的子序列最大和。而这两个只需要累加一遍找最大值即可。
时间复杂度O(nlogn),空间复杂度O(1)
4. 代码B
class Solution {
public:
int maxSubArray(vector<int>& nums) {
return maxSubArrayRange(nums, 0, nums.size() - 1);
}
int maxSubArrayRange(vector<int>& nums, int l, int r)
{
if(l == r) return nums[l];
int mid = (l + r) >> 1;
return max(
max(maxSubArrayRange(nums, l, mid), maxSubArrayRange(nums, mid + 1, r)),
maxSubArrayLeft(nums, l, mid) + maxSubArrayRight(nums, r, mid + 1));
}
int maxSubArrayLeft(vector<int>& nums, int l, int pos)
{
int sum = 0,ret = nums[pos];
for(int i = pos; i >= l; i --)
{
ret = max(sum += nums[i], ret);
}
return ret;
}
int maxSubArrayRight(vector<int>& nums, int r, int pos)
{
int sum = 0,ret = nums[pos];
for(int i = pos; i <= r; i ++)
{
ret = max(sum += nums[i], ret);
}
return ret;
}
};