导航菜单

最大子数组和

🟡 中等

题目描述

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

示例 1

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

示例 2

输入:nums = [1]
输出:1
解释:连续子数组 [1] 的和最大,为 1

示例 3

输入:nums = [5, 4, -1, 7, 8]
输出:23
解释:连续子数组 [5, 4, -1, 7, 8] 的和最大,为 23

提示

  • 1 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10^4

解法一

参考答案 (2 个标签)
动态规划 O(n)

思路

定义 dp[i] 表示以 nums[i] 结尾的最大子数组和。状态转移方程:

  • dp[i] = max(nums[i], dp[i-1] + nums[i])

即要么从当前元素重新开始,要么延续之前的子数组。

代码实现

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

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

解法二

参考答案 (2 个标签)
Kadane算法 O(1)空间

思路

由于 dp[i] 只依赖于 dp[i-1],可以用一个变量代替数组。

代码实现

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

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

图解

nums:     [-2,  1, -3,  4, -1,  2,  1, -5,  4]
current:  [-2,  1, -2,  4,  3,  5,  6,  1,  5]
maxSum:   [-2,  1,  1,  4,  4,  5,  6,  6,  6]

搜索