[前端]_一起刷leetcode 53. 最大子数组和

358 阅读2分钟

这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战

题目

53. 最大子数组和

给你一个整数数组 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

思路

  • 常规做法我们可以采用双重for循环枚举每一种可能性,然后维护一个前缀和二维数组的空间,用来记录从ij中的元素累加的和是多少;

  • 然而实际上我们在解决这些最大和的时候,大部分题目可以采用贪心来做,所谓的贪心,就是尽可能维持你前面部分的和越大越好;

  • 举个例子,如果前面的第一个元素是3, 我们累加起来, 第二个元素是-2,这时候我们加不加呢?答案是肯定的,因为3 - 2 > 0, 只要前面是大于0的部分我们就累加起来,小于0的部分我们就舍去从头开始,然后最终判断每一次累加后的值,取其中的最大值作为我们的答案;

    如: [3, -2, 3] 这个数组:

       - 初始值: 前缀prev为0, 最大值result为最小的数字
       
       - 第一轮的时候: 前缀累加变成3, 最大值取原本的值和当前前缀的最大值为3
       
       - 第二轮的时候: 前缀累加变成1, 最大值取原本的值和当前前缀的最大值为3
       
       - 第三轮的时候: 前缀累加变成4, 最大值取原本的值和当前前缀的最大值为4
       
    

    很多小伙伴在遇到-2的时候就会想着从0开始从新计算了,这是这道题目比较容易陷入的一个误区。

  • 这样子只需要经过一轮遍历我们就可以找到我们要的答案,同时空间复杂度为O(1)。

实现

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    // 记录前缀
    let prev = 0;
    // 记录最大值结果
    let result = Number.MIN_SAFE_INTEGER;

    // 一轮循环,枚举结果
    for (let i = 0; i < nums.length; i++) {
        // 当前最大前缀加当前值和我们上一轮的最大值比较
        result = Math.max(result, nums[i] + prev);
        // 前缀保证是正值,如果是负值就舍去
        prev = Math.max(prev + nums[i], 0);
    }

    return result;
};

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。