Kyyy 动态规划入门 最大连续子数组和

Problem_link: 53. 最大子数组和

方法一 O(N) C(N)

思路

题目要求找出前n个元素连续和最大的子序列,遇到这种有子问题求最值的题目都可以使用动态规划解决。

解题方法

定义 d p [ i ] dp[i] dp[i]表示前 i + 1 i+1 i+1个元素连续和的最大值。

对任意nums[i]都可以作为前i个元素累加的结尾或是下一个子序的开头。
比如nums = [-2,1],前1个元素时必须选

  1. 所以此时的最大值( m a x max max)是-2
  2. dp[0]也是-2

前2个元素的时

  1. 可以选择累加( d p [ i − 1 ] + n u m s [ i ] dp[i-1]+nums[i] dp[i1]+nums[i]),即作为前i+1个元素累加的结尾
  2. 不累加,就是 d p [ i ] = n u m s [ i ] dp[i] = nums[i] dp[i]=nums[i],即作为下一个子序的开头
  3. 取两种选择中的较大值,一个很简单的逻辑,如果前i+1个元素的合还没有nums[i]一个元素值大,那么选nums[i]就行了。

返回 d p dp dp数组中的最大值即可。

复杂度

  • 时间复杂度:
    O ( n ) O(n) O(n)

  • 空间复杂度:
    O ( n ) O(n) O(n)

Code

class Solution {
public:
    int max(int a,int b){
        return a>b?a:b;
    }
    int maxSubArray(vector<int>& nums) {
        vector<int> dp(nums.size(),0);  // 长度和nums一直,元素初始化为0
        dp[0] = nums[0];   // 初始化
        int res = dp[0];

        for(int i=1;i<nums.size();i++){ // 遍历所有
            dp[i] = max(dp[i-1]+nums[i],nums[i]);
            res   = max(dp[i],res);     // 更新最大值
        }
        return res;
    }
};

可以发现每次递推只用了 d p [ i − 1 ] 和 d p [ i ] dp[i-1]和dp[i] dp[i1]dp[i]两个,所以只需要用变量保存,就可以优化到常量空间。

方法一空间优化 C(1)


class Solution {
public:
    int max(int a,int b){
        return a>b?a:b;
    }
    int maxSubArray(vector<int>& nums) {
        int res = -100000;  // 初始化最大值
        int ans = 0;        // 表示前i+1个元素的合,没有元素则为0
        for(auto x:nums){
            ans += x;
            res = max(ans,res);  // dp[i] = max(dp[i-1]+nums[i],res)
            // 如果ans已经是负数了,它就无法为后面的元素提供增量
            // 所以就把开头移到新的位置就行了
            if(ans<0) ans = 0;
        }
        return res;
    }
};

总结

这道题就好比:过去如果不能是你未来的阶梯,那就抛弃它,从当下开始。现实总是更复杂,不能一句概括

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值