LeetCode 53 最大子序和 轻松学会Kadane算法

本文介绍了LeetCode 53题的最大子序和问题,通过Kadane算法来求解,并提供了JavaScript实现。文章详细解释了算法思路,包括如何将数组元素分为两类以及算法的标准解释,同时分享了代码优化后的性能提升,帮助读者深入理解并掌握该算法。

最大子序和

LeetCode 53 力扣 53. 最大子序和

思路

nums[0] 记录当前子串和;遍历按个加元素,如果加之后maxSum更大就更新其数值;

遍历:

  • 如果 sum <= 0,那么后面的子序列肯定不包含目前的子序列,所以令sum = num
  • 如果sum > 0,加上当前元素能使后面的子序列和更大,所以sum += num
    let maxSum = 0;
    let sum = nums[0]; // 记录当前和
    // 按个加,如果加之后maxSum更大就更新
    for (var num in nums){
        if (sum <= 0){
            // 如果sum<=0,那么后面的子序列肯定不包含目前的子序列,所以令sum = num
            sum = num;
        } else {
            // 如果sum > 0,加上当前元素能使后面的子序列和更大
            sum += num;
        }
        maxSum = Math.max(maxSum, sum)
    }
    return maxSum;

Result1

  • 执行用时:92 ms, 在所有 JavaScript 提交中击败了58.27%的用户
  • 内存消耗:39.5 MB, 在所有 JavaScript 提交中击败了22.66%的用户

Kadane算法和代码优化

  • 可以用于求maximum value of a subarray,最大子串和、最大子串积等等;
  • 也就是上面代码里的分割子串思路:遍历数组时把可能遇到的子串元素分成两类,一类拥有和为正数的前缀子串(前面连着的几个元素),另一类的前缀子串和为负;
  • 因为我们需要取得连续的子串,所以对于后一类来说,我们可以直接将当前元素作为待选最大子串和子串的开头,继续遍历;
  • 如果前缀子串和大于零,此前缀子串很有可能就是我们想要的结果,所以可以保留,直接把当前元素加到这个子串里就好。

更标准的算法解释

(Reference From: 求和最大子串(Kadane算法) 算法简明推理 - 代码天地)

  • 目标:前缀子串和与后缀子串和均大于0
  • 我们分割原数组成若干子串。切割方式:

    1. 子串和小于0(除了最后一个子串之外)
    2. 子串的前缀子串和大于0
  • 由1,2我们推得

    1. 子串的后缀子串和小于0
  • 由1,3推得

    1. 目标是某一子串的子串(即目标不可能跨越多个子串)
  • 然后由2,4推得

  • 目标是某子串的前缀子串

  • 最终,我们在分割子串的过程中就能把目标的和(或者是目标)求出来。

代码优化

var maxSubArray = function(nums) {
    let maxSum = nums[0];
    let sum = 0; // 记录当前和
    // 按个加,如果加之后maxSum更大就更新
    for (const num of nums){
        sum = Math.max(num + sum, num);
        maxSum = Math.max(maxSum, sum);
    }
    return maxSum;
};

Result2

  • 执行用时:80 ms, 在所有 JavaScript 提交中击败了94.45%的用户
  • 内存消耗:39 MB, 在所有 JavaScript 提交中击败了95.11%的用户
  • 心得:不知不觉就学会了一种名字听起来很高级的算法(还是CMU教授设计的) 😀

易错点

⚠️sum = Math.max(num + sum, num)而不是sum = Math.max(num + sum, sum)!是将前缀子串和+当前元素值(不加前缀子串和的)当前元素值 进行比较,从而分离两类子串。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值