【DP】LeetCode 53. 最大子数组和
题目链接
思路
分析动态规划题目的时候只需要考虑最后一个阶段,因为所有的阶段转化都是相同的,考虑最后一个阶段容易发现规律
在数组的动态规划问题中,一般 dp[i]
都是表示以 nums[i]
为结尾的状态;dp[i][j]
分别表示 以 nums1[i]
和 nums2[j]
为结尾的状态,以此类推
表示状态
首先构思一下我们需要存储的信息,以此来确定 dp
数组的维数:
- 下标
- 最大和,即当前状态值
因为只有两项信息需要存储,所以可以使用一维数组。
我们用 \(dp[i]\) 表示表示以 \(nums[i]\) 结尾的连续子数组的最大和。
找状态转移方程
这里直接给出状态转移方程,因为我也不知道该怎么解释
\[dp[i] = \left\{
\begin{aligned}
& nums[i] + dp[i - 1], & dp[i - 1] \geq 0, \\
& nums[i], & dp[i - 1] < 0.
\end{aligned}
\right.
\]
边界处理
很容易知道 \(dp[0] = nums[0]\),并且 \(result = nums[0]\)
空间优化
因为 \(dp[i]\) 只和 \(dp[i-1]\) 有关,所以可以不断更新维护单变量 sum
求出最终结果。
代码
dp
数组版
class Solution {
public int maxSubArray(int[] nums) {
int[] dp = new int[nums.length];
int result = nums[0];
dp[0] = nums[0];
for(int i = 1; i < nums.length; i++){
if(dp[i - 1] < 0){
dp[i] = nums[i];
}else{
dp[i] = nums[i] + dp[i - 1];
}
result = Math.max(result, dp[i]);
}
return result;
}
}
空间优化版
class Solution {
public int maxSubArray(int[] nums) {
int result = nums[0];
int sum = nums[0];
for(int i = 1; i < nums.length; i++){
if(sum < 0){
sum = nums[i];
}else{
sum = nums[i] + sum;
}
result = Math.max(result, sum);
}
return result;
}
}