区间动态规划例题:最大子数组和问题(允许最多删除一个元素)
字数 1653 2025-10-30 23:46:49

区间动态规划例题:最大子数组和问题(允许最多删除一个元素)

题目描述
给定一个整数数组 nums,要求找到其连续子数组的最大和,但允许从子数组中最多删除一个元素(也可以不删除)。例如,对于数组 [1, -2, 0, 3],删除元素 -2 后,子数组 [1, 0, 3] 的和为 4,这是最大和。你需要设计一个算法计算这个最大和。

解题过程

  1. 问题分析
    本题是经典最大子数组和问题(Kadane算法)的变种,允许删除一个元素意味着子数组可以是连续的,但允许跳过一个负数元素。核心挑战在于如何通过动态规划记录删除与不删除两种状态。

  2. 状态定义
    定义两个动态规划数组:

    • dp_no_delete[i]:表示以第 i 个元素结尾,且未删除任何元素的最大子数组和。
    • dp_delete[i]:表示以第 i 个元素结尾,且已删除一个元素(可能是当前元素或之前的某个元素)的最大子数组和。
  3. 状态转移方程

    • 未删除状态dp_no_delete[i]):
      与Kadane算法相同,要么继承前一个未删除状态的和并加上当前元素,要么从当前元素重新开始:

\[ dp\_no\_delete[i] = \max(dp\_no\_delete[i-1] + nums[i], nums[i]) \]

  • 已删除状态dp_delete[i]):
    有两种可能:
    1. 删除当前元素:直接继承以 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]) \]

  1. 初始条件

    • i=0(数组第一个元素):
      • dp_no_delete[0] = nums[0](只有一个元素时,最大和即自身)。
      • dp_delete[0] = 0(删除唯一元素后子数组为空,和为0,但题目允许不删除,因此需考虑不删除的情况)。
  2. 遍历与结果计算

    • i=1 开始遍历数组,更新 dp_no_delete[i]dp_delete[i]
    • 最终最大和为所有 dp_no_delete[i]dp_delete[i] 中的最大值(注意:dp_delete[i] 可能为负,但题目允许子数组为空时和为0,需与0比较)。
  3. 示例演示
    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) = 1
    • i=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) = 1
    • i=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
  4. 复杂度分析
    时间复杂度:O(n),空间复杂度:O(n)(可优化为O(1),仅保留前一个状态)。

区间动态规划例题:最大子数组和问题(允许最多删除一个元素) 题目描述 给定一个整数数组 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 ] \] 保留当前元素但之前已删除过某个元素:继承以 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) = 1 i=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) = 1 i=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),仅保留前一个状态)。