原题地址:https://leetcode-cn.com/probl...
repo地址:https://github.com/pigpigever...
原文链接:https://segmentfault.com/a/1190000021026302

题目剖析🧐

题目描述📄

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

思路分析💡

这道题其实可以直接从题目提供的输入输出着手,对于输入为:[ -2, 1, -3, 4, -1, 2, 1, -5, 4 ] 的详细分析如下:

  • 对于输入为 [ -2 ] 的情况,那么结果显然是 -2
  • 对于输入为 [ -2, 1 ] 的情况,最程序化的比较当然是比较这三个结果的大小:-2-2 + 11 的大小对不对?因为从黑盒的角度上看我们并不能一眼看出结果,不过结果当然是 1
  • 对于输入为 [ -2, 1, -3 ] 的情况,我们依然像一个机器人一样列出来:-2-2 + 1-2 + 1 + (-3)11 + (-3)-3,但是我们注意到刚才列出来的情况里面:-2-2 + 11 都是 [ -2, 1 ] 里的情况,所以结论就是:求 [ -2, 1, -3 ] 的 「最大子序列和」 也就是求 [ -2, 1 ] 的 「最大子序列和」和 -3 之间的「最大子序列和」
  • ...

根据上面推导过程中的结论我们可以把它归纳成一个状态转移方程,定义如下:

定义一个序列 S[i],存在元素为 A[i],当 i = 0 时,S[0] = A[0]
i > 0 时, S[i] = max{S[i - 1] + A[i], A[i]}

示例代码

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    const dp = [nums[0]], len = nums.length
    let max = dp[0]
    for (let i = 1; i < len; i++) {
        dp[i] = Math.max(dp[i - 1] + nums[i], nums[i])
        max = Math.max(dp[i], max)
    }
    return max
};

不过这里的空间复杂度可以优化下👇

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    let ans = nums[0], max = nums[0]
    for (let i = 1; i < nums.length; i++) {
        ans = Math.max(nums[i] + ans, nums[i])
        nums[i] = ans
        max = Math.max(ans, max)
    }
    return max
};

写在最后

一直在 LeetCode 上刷题,之前还加入了组织,有兴趣加入一起学习的同学可以在下方留言或者关注我的微信公众号「tony老师的前端补习班」并在后台留言,可以进群跟大佬们一起学习。


tonychen
1.2k 声望272 粉丝