区间动态规划例题:最大子数组和问题(允许最多删除一个元素)
字数 1653 2025-10-30 23:46:49
区间动态规划例题:最大子数组和问题(允许最多删除一个元素)
题目描述
给定一个整数数组 nums,要求找到其连续子数组的最大和,但允许从子数组中最多删除一个元素(也可以不删除)。例如,对于数组 [1, -2, 0, 3],删除元素 -2 后,子数组 [1, 0, 3] 的和为 4,这是最大和。你需要设计一个算法计算这个最大和。
解题过程
-
问题分析
本题是经典最大子数组和问题(Kadane算法)的变种,允许删除一个元素意味着子数组可以是连续的,但允许跳过一个负数元素。核心挑战在于如何通过动态规划记录删除与不删除两种状态。 -
状态定义
定义两个动态规划数组:dp_no_delete[i]:表示以第i个元素结尾,且未删除任何元素的最大子数组和。dp_delete[i]:表示以第i个元素结尾,且已删除一个元素(可能是当前元素或之前的某个元素)的最大子数组和。
-
状态转移方程
- 未删除状态(
dp_no_delete[i]):
与Kadane算法相同,要么继承前一个未删除状态的和并加上当前元素,要么从当前元素重新开始:
- 未删除状态(
\[ dp\_no\_delete[i] = \max(dp\_no\_delete[i-1] + nums[i], nums[i]) \]
- 已删除状态(
dp_delete[i]):
有两种可能:- 删除当前元素:直接继承以
i-1结尾的未删除状态(即跳过nums[i]):
- 删除当前元素:直接继承以
\[ \text{option1} = dp\_no\_delete[i-1] \]
2. 保留当前元素但之前已删除过某个元素:继承以 `i-1` 结尾的已删除状态并加上当前元素:
\[ \text{option2} = dp\_delete[i-1] + nums[i] \]
综合两者:
\[ dp\_delete[i] = \max(dp\_no\_delete[i-1], dp\_delete[i-1] + nums[i]) \]
-
初始条件
- 当
i=0(数组第一个元素):dp_no_delete[0] = nums[0](只有一个元素时,最大和即自身)。dp_delete[0] = 0(删除唯一元素后子数组为空,和为0,但题目允许不删除,因此需考虑不删除的情况)。
- 当
-
遍历与结果计算
- 从
i=1开始遍历数组,更新dp_no_delete[i]和dp_delete[i]。 - 最终最大和为所有
dp_no_delete[i]和dp_delete[i]中的最大值(注意:dp_delete[i]可能为负,但题目允许子数组为空时和为0,需与0比较)。
- 从
-
示例演示
以nums = [1, -2, 0, 3]为例:- 初始化:
dp_no_delete[0] = 1,dp_delete[0] = 0 i=1:
dp_no_delete[1] = max(1 + (-2), -2) = -1
dp_delete[1] = max(dp_no_delete[0], dp_delete[0] + (-2)) = max(1, 0-2) = 1i=2:
dp_no_delete[2] = max(-1 + 0, 0) = 0
dp_delete[2] = max(dp_no_delete[1], dp_delete[1] + 0) = max(-1, 1) = 1i=3:
dp_no_delete[3] = max(0 + 3, 3) = 3
dp_delete[3] = max(dp_no_delete[2], dp_delete[2] + 3) = max(0, 1+3) = 4- 最终结果:
max(3, 4, 0) = 4。
- 初始化:
-
复杂度分析
时间复杂度:O(n),空间复杂度:O(n)(可优化为O(1),仅保留前一个状态)。