LeetCode 53. 最大子数组和
本节目标
维护必须以当前位置结尾的最大连续和,避免把不连续正数相加。
这是动态规划基础与线性状态中“连续区间必须收尾”的母题。
题意与约束
求非空连续子数组的最大和;元素可为负数,答案不能默认为零。
第一反应与重复子问题
处理当前位置时,只需判断是从它重新开段,还是接在前一个连续段之后;“以前一位结尾”的答案会重复使用。
状态定义与转移推导
令 dp[i] 为必须以 i 结尾的最大和,dp[i]=max(nums[i], dp[i-1]+nums[i])。全局答案是所有 dp[i] 的最大值。
正确性依据
任何以 i 结尾的连续段,前面要么为空,要么恰是以 i-1 结尾的连续段;取两者较优即穷尽所有可能。
样例执行过程
在 [-2,1,-3,4,-1,2,1,-5,4] 中,结尾状态到 4,-1,2,1 时形成和为 6 的段。
代码实现
- C++
- Python
C++17
#include <algorithm>
#include <vector>
using namespace std;
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int endingHere = nums[0], best = nums[0];
for (int index = 1; index < static_cast<int>(nums.size()); index++) {
endingHere = max(nums[index], endingHere + nums[index]);
best = max(best, endingHere);
}
return best;
}
};
Python 3
class Solution:
def maxSubArray(self, nums: list[int]) -> int:
ending_here = best = nums[0]
for value in nums[1:]:
ending_here = max(value, ending_here + value)
best = max(best, ending_here)
return best
复杂度分析
一次扫描,时间 O(n),滚动状态空间 O(1)。
边界与易错点
- 全负数组必须返回其中最大的元素。
- 状态必须规定“以当前位置结尾”,否则会错误拼接不连续元素。
模式迁移
最大乘积子数组在同一框架上额外维护最小值;环形数组版本则需分开处理首尾连接。