You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

最多可省略k个元素时最大和连续子数组的解法问询

最多省略k个元素的最大连续子数组和解法

嘿,你的动态规划思路方向完全正确!咱们来把这个问题的解法理清楚,尤其是你困惑的状态递推逻辑,再看看其他可行的解法~

一、动态规划解法(最通用高效)

状态定义

你提到的dp[i][j]定义非常合适:以第i个元素结尾,最多删除j个元素时的最大子数组和。这里不需要跟踪具体删除了哪些元素,状态转移会自动覆盖所有合法的删除组合。

递推逻辑

对于每个位置i和删除次数j,我们有三种选择:

  1. 保留当前元素,并接在以i-1结尾、最多删j个元素的子数组后面:dp[i-1][j] + arr[i]
  2. 保留当前元素,但重新开始一个子数组(前面的元素都不选):arr[i]
  3. 删除当前元素,此时等价于以i-1结尾、最多删j-1个元素的最大和:dp[i-1][j-1]

取这三种情况的最大值作为dp[i][j]的结果:

dp[i][j] = max(dp[i-1][j] + arr[i], arr[i], dp[i-1][j-1])

边界条件

  • i=0(第一个元素)时,不管允许删除多少次j,我们只能选择保留这个元素(因为子数组不能为空),所以:
    dp[0][j] = arr[0] (对所有j >= 0)
    

空间优化

因为dp[i][j]只依赖于上一行的dp[i-1][j]dp[i-1][j-1],我们可以用一维数组滚动更新,把空间复杂度从O(nk)降到O(k)

  • prev数组存储上一行的结果
  • curr数组计算当前行的结果,更新完成后将prev替换为curr

示例验证

拿你给的例子:arr = [6,-5,3,-7,6,-1,10,-8,-8,8]k=2

  • 计算到第7个元素(索引6,值为10)时,dp[6][2] = max(dp[5][2]+10, 10, dp[5][1])
  • dp[5][2]是前6个元素最多删2个的最大和(即删除-5和-7,和为6+3+6-1=14),加10后得到24,正好是示例中的最优结果。

二、滑动窗口+最小堆解法(适合小规模数组)

如果数组长度n不大,可以用这种思路:

  1. 遍历所有可能的连续子数组窗口
  2. 对每个窗口,计算总和,然后找出窗口中最小的t个元素(t <= k),用窗口总和减去这些元素的和,得到当前窗口能达到的最大和
  3. 遍历所有窗口后取最大值

这种方法的时间复杂度是O(n^2 log k),因为每个窗口找最小t个元素需要用堆排序,适合n较小的场景。

三、思路总结

你之前困惑的“跟踪已移除元素”其实不需要——DP的状态转移已经覆盖了所有可能的删除情况:要么保留当前元素继承之前的状态,要么删除当前元素继承少删一次的状态,所有合法的删除组合都被考虑到了,不会有重复或遗漏。

最后,动态规划解法是最通用的,时间复杂度O(nk),空间优化后是O(k),适合大多数场景。

内容的提问来源于stack exchange,提问作者Muskan Agarwal

火山引擎 最新活动