mengjian-github / leetcode

leetcode前端题目笔记

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

53. 最大子数组和

mengjian-github opened this issue · comments

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

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

 

示例 1:

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

输入:nums = [1]
输出:1
示例 3:

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

这道题最直观的想法是暴力求解,尝试把每个子数组的情况全部计算出来取最大:

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    if (nums.length <= 1) {
        return nums[0];
    }

    function getMax(index) {
        const num = nums[index];
        let sum = num;
        let max = num;

        // 计算以num开头的连续最大和
        for (let i = index + 1; i < nums.length; i++) {
            sum += nums[i];
            if (sum > max) {
                max = sum;
            }
        }
        return max;
    }

    let result = nums[0];

    for (let i = 0; i < nums.length; i++) {
        const max = getMax(i);
        if(max > result) {
            result = max;
        }
    }

    return result;
};

不幸的是,这个复杂度通不过LeetCode

这里采用动态规划是最简单直观的做法,但是dp数组的定义比较特殊:

  • dp数组的含义是以i结尾的最长子数组和,这样才能让dp具有递推关系
  • 递推关系是:dp[i+1] = Math.max(dp[i] + nums[i+1], nums[i+1]),相当于要么和之前的数组结合在一起,要么自己新起一个
/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    let result = nums[0];

    const dp = [nums[0]];   // dp的定义是,以i结尾的最大子数组和

    for (let i = 1; i < nums.length; i++) {
        dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);

        if (dp[i] > result) {
            result = dp[i];
        }
    }
   
    return result;
};