Leetcode53-最大子数组和

139 阅读2分钟

Link:leetcode.cn/problems/ma…
Tag:数组、动态规划
难度:Medium

题目

题目描述:给你一个整数数组 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

提示:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104

题解

思路一:因为数组元素里面有负数,所以滑动数组不太行
思路二:暴力会超时
思路三:看提示可以用动态规划,就有灵感了 起初,设置dp[i][j]=maxvalue,j代表左边界,i代表右边界。改变j进行比较,获得连续子数组和的最大值。【考虑了一下i为左边界、j为左边界的话,没那么方便,好像不能利用动态规划特性(此时的值通过上一个值来更新)】
举例来说,dp[3][0]=max(dp[2][0]+nums[i], ?),感觉?这里需要放的值不太清晰。考虑了之后觉得只需要一个变量即可。dp[i]=nums[i]表示其本身,也是最小子数组,然后不断进行比较。
因为是连续,所以比较当前的值最大还是加上前一个的值最大。
放一个杂乱的草稿截图:

image.png

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        // 最大和--> 连续
        int countSum = accumulate(nums.begin(), nums.end(), 0);
        // 暴力枚举--但应该会不行
        /* 动态规划 dp[i][j] = maxsum  i--子数组右边*/
        vector<long>dp(nums.size(), 0);
        dp[0] = nums[0]; 
        int maxNum = dp[0];
        for(int i = 1; i < nums.size(); i++){
            dp[i] = dp[i - 1] + nums[i] > nums[i] ? dp[i - 1] + nums[i]: nums[i];
            if(dp[i] > maxNum) maxNum = dp[i];
        }
        return maxNum;
    }
};

复杂度分析: 时间复杂度:O(n) 空间复杂度:O(n) → 优化:由于只依赖于前一个,可以改为滚动数组,则复杂度会降为O(1)

结果

image.png