53. 最大子数组和

138 阅读1分钟

[53. 最大子数组和]

「这是我参与2022首次更文挑战的第32天,活动详情查看:2022首次更文挑战」。

题目描述

给你一个整数数组 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  

进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。

思路

这是一道动态规划的题。判定一道题使用动态规划的标准是看当前状态是否依赖之前的状态,即问题由许多重复的子问题组成,在这道题里面,子问题就是以下标i为最后一个元素的连续数组和。之后按照几个步骤,复习一下:

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

具体到这道题:

1、dp数组含义:dp[i] 表示 以下标i为最后一个元素的连续数组最大和

2、递推公式:轮到当前元素的时候,可以在之前的基础上加上当前的元素,也可以重新开始,取最大值。即 dp[i]=max(dp[i-1]+num[i],num[i])

3、初始化:当i=0时,之前没有元素,所以dp[0]需要初始化为num[0]。

4、遍历顺序:由递推公式: dp[i]=max(dp[i-1]+num[i],num[i]),可以推出i 从左到右。

5、省略

代码实现

由于只是依赖前两个状态,所以可以压缩dp数组的大小,写法与昨天的写法类似,但不是很好理解,以下给出不压缩的写法。

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        if (nums.size() == 0) return 0;
        vector<int> dp(nums.size(), 0)
        dp[0] = nums[0];
        int result = dp[0];
        for (int i = 1; i < nums.size(); i++) {
            dp[i] = max(dp[i - 1] + nums[i], nums[i]); // 状态转移公式
            if (dp[i] > result) result = dp[i]; // result 保存dp[i]的最大值
        }
        return result;
    }
};

总结

简要的复习了动态规划,动态规划的一般做题步骤,dp数组等等。