leetcod 53:最大子序和算法理解

动态规划思想

先上代码

class Solution {
    public int maxSubArray(int[] nums) {
        int max = Integer.MIN_VALUE;
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum = Math.max(nums[i], sum + nums[i]);
            max = Math.max(sum , max);
        }
        return max;
    }
}

sum[i]为以第i个元素结尾且和最大的连续子数组。假设对于元素i,所有以它前面的元素结尾的子数组的长度都已经求得,那么以第i个元素结尾且和最大的连续子数组实际上,要么是以第i-1个元素结尾且和最大的连续子数组加上这个元素,要么是只包含第i个元素,即sum[i]= max(sum[i-1] + a[i], a[i])。可以通过判断sum[i-1] + a[i]是否大于a[i]来做选择,而这实际上等价于判断sum[i-1]是否大于0。由于每次运算只需要前一次的结果,因此并不需要像普通的动态规划那样保留之前所有的计算结果,只需要保留上一次的即可,因此算法的时间和空间复杂度都很小。

作者:腾阳
来源:CSDN
原文:https://blog.csdn.net/weixin_41931602/article/details/82891149
版权声明:本文为博主原创文章,转载请附上博文链接!


个人理解:
比如我们我们有这样一个数组 1, 2, 3,我们要判断最大的子序列和,我们先列出所有情况:

332321
221
1

我们从数组后面往前找,在所有的子序列中比较最大值。现在我们按照上面的思想sum[i]= max(sum[i-1] + a[i], a[i]),先从最后一位3开始看起,我们把以最后一个数3的所有子序列列出来并分为两部分,一部分是a[i]即3,另一部分是(sum[i-1] + a[i])

最后一个数剩下的子序列
332, 321, 2, 21,1

后面的序列实际可以拆成 3 + max(21,2),括号里的序列其实就是以2为最后一位数字的最大序列和,依次递归还可以拆成以1为最后数字的最大序列和。所以我们最终能推出动态规划的状态方程sum[i]= max(sum[i-1] + a[i], a[i])。
接着再按照代码的顺序就可以理解。
我们还可以顺便变化一下方程,sum[i-1] + a[i] < a[i] ⇒ sum[i-1] < 0,这个公式说明,如果我们在计算sum和的时候,加上最后一个数如果碰到sum <0时便可以直接丢弃,因为这时sum[i]一定不是最大的子序列和,a[i]此时才是最大的。贴上代码。

class Solution {
    public int maxSubArray(int[] nums) {
       int sum = 0, sumMax = nums[0];
        for(int i = 0; i < nums.length; i++){
            sum += nums[i];
            if(sum > sumMax){
                sumMax = sum;
            }
            if(sum < 0){
                sum = 0;
            }
        }
        return sumMax;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值