LeetCode53、最大子数组和

45 阅读1分钟

LeetCode 系列记录我学习算法的过程。

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

题目

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

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

示例:

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


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


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

提示

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104

进阶: 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。

思路

根据题目及示例,可知给定的数组是一个无序的数组,需在无序数组中找到子项之和最大的连续子数组

这个题目虽然是简单难度,但是看了半天我也没想出什么好的实现方法,只想到暴力法遍历所有情况

但是在写代码理清思路的时候,突然发现一种规律,当遍历到一个新的数组项时,如果与前面记录的子数组和相加

小于当前项时,那前面的和肯定小于 0,需要舍弃,反正则相加,与记录的最大和比较并替换

最后返回记录的最大和即可

代码实现

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    // max 记录的最大和
    // temp 当前子数组和
    let max = temp = nums[0]
    let i = 1
    while(i < nums.length) {
        // 如果子数组和加上当前项后大于当前项,则子数组和大于 0,可以保留,记录相加之和
        if(temp + nums[i] > nums[i]) {
            temp += nums[i]
        } else {
            // 反正子数组和小于等于 0,舍弃,temp 替换为当前项
            temp = nums[i]
        }
        // 重新判断最大和
        max = Math.max(max, temp)
        // 移动下标
        i++
    }
    // 返回记录的最大和
    return max
};

image.png

优化

其他解题思路和我想的都差不多,这种方法属于动态规划,不过有些写法比较简洁:

var maxSubArray = function(nums) {
    let sum = 0, max = nums[0]
    // 遍历数组
    nums.forEach((n) => {
        // 子数组和
        sum = Math.max(sum + n, n)
        // 记录的最大和
        max = Math.max(max, sum)
    })
    return max
};

还有一种方法是分治法,暂时看不懂,先记录下来以后再来研究一下😂

function Status(l, r, m, i) {
    this.lSum = l;
    this.rSum = r;
    this.mSum = m;
    this.iSum = i;
}

const pushUp = (l, r) => {
    const iSum = l.iSum + r.iSum;
    const lSum = Math.max(l.lSum, l.iSum + r.lSum);
    const rSum = Math.max(r.rSum, r.iSum + l.rSum);
    const mSum = Math.max(Math.max(l.mSum, r.mSum), l.rSum + r.lSum);
    return new Status(lSum, rSum, mSum, iSum);
}

const getInfo = (a, l, r) => {
    if (l === r) {
        return new Status(a[l], a[l], a[l], a[l]);
    }
    const m = (l + r) >> 1;
    const lSub = getInfo(a, l, m);
    const rSub = getInfo(a, m + 1, r);
    return pushUp(lSub, rSub);
}

var maxSubArray = function(nums) {
    return getInfo(nums, 0, nums.length - 1).mSum;
};