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());
    }
};


















