算法 | 动态规划 | 剑指 Offer 42. 连续子数组的最大和

367 阅读1分钟

题目

输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

要求时间复杂度为O(n)。

示例1:

输入: nums = [-2,1,-3,4,-1,2,1,-5,4]

输出: 6

解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/li…

名词解释

nums 数组

max 最大值

total 数组中部分元素的和

题解

1. 设nums初始长度为1

max = nums[0]

2. 在第一步的基础上增加nums[1]使得nums长度为2

可分组为:nums[0]nums[1]nums[0]+nums[1]

与步骤1对比新增了nums[1]nums[0] + nums[1]

对新增的部分求值

由于负数会使合减少,所以用以下方式求total

if (nums[0] <= 0) total = nums[1]

if (nums[0] > 0) total = nums[0] + nums[1]

然后可求最大值为

max = Max(nums[0], total)

3. 在第二步的基础上增加nums[2]使得nums长度为3

可分组为:nums[0]nums[1]nums[0] + nums[1]nums[2]nums[1] + nums[2]nums[0] + nums[1] + nums[2]

与步骤2对比新增了nums[2]nums[1] + nums[2]nums[0] + nums[1] + nums[2]

对新增的部分求值

if (nums[0] <= 0) total = nums[1] + nums[2] 或 nums[2]

if (nums[0] > 0) total = nums[0] + nums[1] + nums[2] 或 nums[2]

结合步骤2,将步骤2中的total记为total1max记为max1,将步骤3中的total记为total2max记为max2

那么可得

if (nums[0] <= 0) total1 = nums[1]

if (nums[0] > 0) total1 = nums[0] + nums[1]

推算可得

total2 = total1 + nums[2]

再推算可得

if (total <= 0) total2 = nums[2]

if (total > 0) total2 = total1 + nums[2]

然后可求最大值 max2 = Max(max1, total2)

4. 推算通用公式

if (dp[i-1] > 0) dp[i] = dp[i-1] + nums[i]

if (dp[i-1] <= 0) dp[i] = nums[i]

js代码

const maxSubArray = function(nums) {
    let max = nums[0]
    nums.reduce((preItem, curItem, index)=> {
        if(preItem>0) preItem += curItem
        else preItem = curItem
        max = max > preItem ? max : preItem
        return preItem
    })
    return max
};