题目:
Given an integer array nums
, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Example 1:
Input: nums = [-2,1,-3,4,-1,2,1,-5,4] Output: 6 Explanation: [4,-1,2,1] has the largest sum = 6.
Example 2:
Input: nums = [1] Output: 1
Example 3:
Input: nums = [5,4,-1,7,8] Output: 23
Constraints:
1 <= nums.length <= 3 * 104
-105 <= nums[i] <= 105
Follow up: If you have figured out the O(n)
solution, try coding another solution using the divide and conquer approach, which is more subtle.
思路1:
首先这个排除用滑动窗口的方法,因为左侧可能是负数,那么左端的向右移动是无法判断的,这里我们采用DP。显是设定空的DP数组,转移方程的思路是当前这个数字,要么我要,要么不要,而这个数字又可能是负数,因此每次DP[i]的选择,只需要在中取最大的即可。最终返回最大的DP[i]即可。
代码1:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n =nums.size();
vector<int> dp(n,0);
dp[0]=nums[0];
int ans=nums[0];
for(int i=1;i<n;i++)
{
dp[i]=max(nums[i],dp[i-1]+nums[i]);
ans=max(dp[i],ans);
}
return ans;
}
};
思路2:
从思路1中可以看见当前DP[i]只和DP[i-1]有关系,那么可以压缩为不用额外DP数组而是用一个数字。用这个数字记录前面的和,每次更新答案,如果当前和小于0,那么我们直接抛弃它,令和等于0。这里可能会有疑问如果全是负数怎么办,其实即使全是负数,在抛弃它之前我们也已经记录下了答案,因此没有关系。另一点是答案ans的初始化为nums[0],如果全是负数,那么初始化的答案也是负数,依然成立,并不会出现全是负数返回0的情况。
代码2:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int sum=0;
int ans=nums[0];
for(int i:nums)
{
sum+=i;
ans=max(ans,sum);
if(sum<0)
sum=0;
}
return ans;
}
};