[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为最后一个元素的连续数组和。之后按照几个步骤,复习一下:
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导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数组等等。