[leetcode]53. 最大子序和*
53. 最大子序和
Difficulty: 简单
给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
Solution 1.0
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int size = nums.size();
if(size == 0) return 0;
vector<int> sum; sum.resize(size);
sum[0] = nums[0];
for(int i = 1; i< size; ++i) {
sum[i] = max(sum[i-1] + nums[i],nums[i]);
}
return *max_element(sum.begin(),sum.end());
}
};
思路
遍历当前数组,如果当前位置之前的全部元素和为正值,则算上当前元素结果必然为最大,否则,如果全部元素和为负数,那么以当前元素作为最大值即可。动归的状态转移方程为
dp[i] = nums[i] + (dp[i-1] > 0?dp[i-1]:0)
当然,从递推式可以发现,其实并不需要储存全部元素,只需要前后两个元素即可,因此可以缩小空间复杂度。最终,时间复杂度O(n),空间复杂度O(n)。
Solution 1.1 优化版
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int size = nums.size();
if(size == 1) return nums[0];
int pre = nums[0],cur = nums[1],maximum = nums[0];
for(int i = 1; i < size;++i){
cur = nums[i] + (pre >= 0 ? pre : 0);
maximum = max(cur,maximum);
pre = cur;
}
return maximum;
}
};
思路
减少了空间复杂度。最终,时间复杂度O(n),空间复杂度O(1)。
*Solution 2 分治法
思路
最优解的三种可能:
1.完全在中间位置的左侧
2.完全在中间位置的右侧
3.包含中间位置