53. 最大子数组和(中等)
思路
这道题的状态设计和状态转移和 300. 最长递增子序列
类似。但是这里要求的是连续子数组,和子序列不同。
状态定义
首先定义 dp[i]
:以 nums[i] 结尾的具有最大和的连续子数组。
状态转移方程
根据状态的定义,dp[i] 一定包含 nums[i]。
这里我们假设 nums[i] > 0,则一定有 dp[i] = dp[i-1] + nums[i]
,对于 dp[i-1] 无非两种情况,要么 >= 0 ,要么小于 0。
- 如果
dp[i-1] >= 0
,此时再加入 nums[i],能够得到和更大的连续子数组; - 如果
dp[i-1] < 0
,那么 nums[i] > dp[i-1] ,所以可以构建新的连续子数组,只包含 nums[i] 这个元素,即dp[i] = nums[i];
。
综合上述两种情况,我们可以统一考虑,即 dp[i] = max(nums[i], dp[i-1] + nums[i]);
初始化
dp[0] 意味着以 nums[0] 结尾,因此连续子数组中只包含 nums[0], 那么此时连续子数组的和为 nums[0] 的值,即 dp[0] = nums[0];
。
返回的最终结果
这道题和一般的动态规划不一样,不是直接返回dp[n-1],而是要返回以 nums[i] 结尾的所有情况中的最大值,即 return *max_element(dp.begin(), dp.end());
。
代码
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
vector<int> dp(n);
dp[0] = nums[0];
for(int i=1; i<n; ++i){
dp[i] = max(nums[i], dp[i-1] + nums[i]);
}
return *max_element(dp.begin(), dp.end());
}
};