53. 最大子数组和
Origin: LeetCode 53
题目描述
给定一个整数数组 nums,找出具有最大和的连续子数组(至少包含一个元素),返回其最大和。
示例
Input: nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
Output: 6
Explanation: 连续子数组 [4, -1, 2, 1] 的和最大,为 6。
Input: nums = [1]
Output: 1
Input: nums = [5, 4, -1, 7, 8]
Output: 23
约束
- 1 <= nums.length <= 10
- -10^4 <= nums[i] <= 10
关键信息
- 连续子数组(不是子序列)
- 至少包含一个元素
- DP:dp[i] = max(nums[i], dp[i-1] + nums[i])
- 可优化为 O(1) 空间
Resolution
我的解法(滚动变量 O(1) 空间)
function maxSubArray(nums: number[]): number {
let pre = nums[0]
let max = nums[0]
for (let i = 1; i < n; i++) {
pre = Math.max(pre + nums[i], nums[i])
max = Math.max(pre, max)
}
return max
}数组版(O(n) 空间,第一版)
function maxSubArray(nums: number[]): number {
const n = nums.length
let res = Array.from({ length: n }, () => 0)
res[0] = nums[0]
for (let i = 1; i < n; i++) {
res[i] = Math.max(res[i - 1] + nums[i], nums[i])
}
return Math.max(...res)
}解题思路
dp[i] = max(nums[i], dp[i-1] + nums[i])。要么从当前元素重新开始,要么接着前面的和。
滚动变量优化:不需要数组,只用 pre 记录前一个状态,max 记录全局最大值。
踩坑
- 返回值不是 dp[n-1],最大和可能出现在中间,要返回 Math.max(…dp) 或滚动维护 max
- DP 方程不是 max(dp[i-1]+nums[i], dp[i-1])(子序列思路),是 max(nums[i], dp[i-1]+nums[i])(连续子数组)
复杂度
- 时间:O(n)
- 空间:O(1),滚动变量