《leetcoed53. 最大子序和》

168 阅读2分钟

题目:

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

示例:

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

分析:一个数组,它的所有连续子数组有非常多种可能,还要从所有的连续子数组里找到和最大的那个,如果挨个遍历,列举出所有的子数组,暴力求解,非常麻烦。

采用动态规划的思路:所有的连续子数组有一种规律,可以看成以每一个元素为结尾,能形成的所有连续子数组。比如索引i处的元素nums[i](如i=3),以它为结尾,能形成的连续子数组有:[4] [-3,4] [1,-3,4] [-2,1,-3,4] 四种可能。我们记f(i)为以i位置元素结尾的连续子数组中的最大和。然后遍历数组,求出每一个位置的这样一个f,然后这些f中的最大值,自然就是整个数组的最大和的连续子数组。

那么f(i)怎么确定呢?发现f(i)和f(i-1)有关。假设我们已经求出了f(i-1),也就是i处元素的前一个元素为结尾的最大和连续子数组。因为一定要是连续的,所以f(i)一定包括nums[i] ,这个位置自己的元素。所以f(i)要么是nums[i] 自己,要么是nums[i]和前一段f(i-1)连上,就看他俩谁更大,就要谁。因为f(i-1)已经是前边能取的最大的和了。

综上,我们可以用一个数组f保存每一个位置元素为结尾的连续子数组的最大和。遍历整个数组一次,每次根据f[i-1]对应求出f[i],初始化f[0]是第一个元素nums[0] 。遍历出来以后,f数组就有了,然后取这个f的最大值。时间复杂度O(n),空间复杂度O(n)

不用数组f保存,改成用变量保存上一个最大和,遍历的同时保存下上一个最大和和当前最大和的较大值

var maxSubArray = function(nums) {
    let last=nums[0],max=nums[0],now
    for(let i=1;i<nums.length;i++){
        now=Math.max(nums[i],last+nums[i])
        last=now
        max=Math.max(max,now)
    }
    return max
};