解法1:贪心
思想:
如果当前和为负,就抛弃当前和,从下一个数开始。如果当前和为正,就继续使用。每遇到一个数就更新一次最大和。
复杂度:
时间:O(n)
空间:O(1)
代码:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int maxsum = INT_MIN;
int sum = 0;
for(int i : nums){
sum += i;
//更新最大和
maxsum = max(maxsum, sum);
//如果当前和为负,就抛弃
sum = sum < 0 ? 0 : sum;
}
return maxsum;
}
};
解法2:动态规划
思想:
●状态定义:dp[i]
代表以元素nums[i]
为结尾的连续子数组最大和。以nums[i]
结尾方便得到转移方程
●转移方程:若dp[i - 1] <= 0
,说明dp[i - 1]
产生了负贡献,抛弃
dp[i - 1] > 0时:dp[i] = dp[i - 1] + nums[i]
dp[i - 1] <= 0时:dp[i] = nums[i]
复杂度:
时间:O(n)
空间:O(n)
代码:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.empty())
return 0;
vector<int>dp(nums.size(), 0);
dp[0] = nums[0];
//使用maxsum来更新目前的最大值
int maxsum = dp[0];
for(int i = 1; i < nums.size(); i++){
//转移方程
if(dp[i - 1] > 0)
dp[i] = dp[i - 1] + nums[i];
else
dp[i] = nums[i];
maxsum = max(maxsum, dp[i]);
}
//不能返回dp[nums.size() - 1],注意dp[i]的意思
return maxsum;
}
};
改进:
dp[i]只与dp[i - 1]有关,所以可以用两个变量来代替,将空间复杂度降至O(1)
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.empty())
return 0;
int pre = nums[0], cur = 0;
//使用maxsum来更新目前的最大值
int maxsum = pre;
for(int i = 1; i < nums.size(); i++){
if(pre < 0)
cur = nums[i];
else
cur = pre + nums[i];
//更新pre
pre = cur;
maxsum = max(cur, maxsum);
}
return maxsum;
}
};