最大连续子数组
class Solution {public int maxSubArray(int[] nums) {int len=nums.length;//创建dp表int[] dp=new int[len];//初始化dp[0]=nums[0];int max=dp[0];//根据状态转移方程填dp表for(int i=1;i<len;i++){dp[i]=Math.max(nums[i],nums[i]+dp[i-1]);max=Math.max(max,dp[i]);}return max;}
}
dp[i]
只是「以第 i 个数结尾」的最大连续子数组和,而题目要求的是 整个数组里「任意」连续子数组的最大和,这两者并不等价。
✅ 举个例子说明
nums = [-2, 1, -3, 4, -1, 2, 1]
i | nums[i] | dp[i] (以 i 结尾的最大和) | 当前全局最大值 |
---|---|---|---|
0 | -2 | -2 | -2 |
1 | 1 | 1 | 1 |
2 | -3 | -2 | 1 |
3 | 4 | 4 | 4 |
4 | -1 | 3 | 4 |
5 | 2 | 5 | 5 |
6 | 1 | 6 | 6 ✅ |
dp[6] = 6
表示「以最后一个元素 1 结尾」的最大连续子数组和是[4, -1, 2, 1]
。- 但全局最大连续子数组和也是 6,恰好落在结尾,纯属巧合。
- 如果数组变成
[5, -10, 3]
,则:dp = [5, -5, 3]
,- 而答案显然是
5
,不是dp[2] = 3
。
✅ 所以必须再扫一遍
int max = dp[0];
for (int i = 1; i < n; i++) {dp[i] = Math.max(nums[i], dp[i-1] + nums[i]);max = Math.max(max, dp[i]); // 这一步就是取“所有以 i 结尾的最大值”里的最大值
}
✅ 一句话总结
dp[i]
只保证「以 i 结尾」的最大连续子数组和;
题目要求的是「全局」最大连续子数组和,因此需要max = Math.max(max, dp[i])
把每一行的结果再取一次最大值。