最大子数组和(动态规划)

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入:nums = [1]
输出:1

示例 3:

输入:nums = [5,4,-1,7,8]
输出:23

思路: 动态规划

我们用 f(i) 代表以第 i 个数结尾的「连续子数组的最大和」,那么很显然我们要求的答案就是:max{f(i)} (0<i<n)

因此我们只需要求出每个位置的 f(i),然后返回 f 数组中的最大值即可。那么我们如何求 f(i) 呢?我们可以考虑 nums[i] 单独成为一段还是加入 f(i−1) 对应的那一段,这取决于 nums[i] 和 f(i−1)+nums[i] 的大小,我们希望获得一个比较大的,于是可以写出这样的动态规划转移方程:

f(i)=max{f(i−1)+nums[i],nums[i]}

 

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        //动态规划
        int n = nums.size();
        vector<int> dp(n,0);
        dp[0] = nums[0];
        int maxValue = dp[0];
        for(int i=1;i<n;i++){
            dp[i] = max(dp[i-1]+nums[i],nums[i]);
            if(dp[i]>maxValue) maxValue = dp[i];
        }
        return maxValue;
    }
};

 方法二:前缀和+最小前缀和

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        //前缀和
        int n = nums.size();
        int pre_sum=0,min_pre_sum=0;
        int ans=INT_MIN;
        for(int i=0;i<n;i++){
            pre_sum +=nums[i];
            ans = max(ans,pre_sum-min_pre_sum);
            min_pre_sum = min(min_pre_sum,pre_sum);
        }
        return ans;
    }
};

 

posted on 2024-12-19 09:41  _月生  阅读(38)  评论(0)    收藏  举报