You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻找满足约束的最大和子序列:能否实现O(n)线性时间复杂度?

嘿,这个问题挺有意思的,我们一步步拆解,看看怎么把复杂度从指数级压下来,甚至摸到线性时间的边界👇

先明确核心条件&预处理

首先,我们先把问题里的四个条件转化成更容易处理的形式,同时做些前置准备:

  1. 预处理前缀和/后缀和:

    • 先算prefix_sum数组:prefix_sum[i]表示数组前i个元素的和(也就是array[0]到array[i-1]的总和),O(n)时间搞定。
    • 再算suffix_sum数组:suffix_sum[i]表示array[i+1]到数组末尾的总和,同样O(n)时间。
      这两个数组能帮我们快速计算任意区间的和,以及某个元素左右侧的总合。
  2. 筛选候选点(满足条件4):
    条件4要求选中的每个索引都是原数组的局部极小值点(边界点特殊处理):

    • 中间索引1<=i<=n-2:必须满足array[i] < array[i-1]且array[i] < array[i+1]
    • 第一个索引i=0:如果数组长度≥2,需要array[0] < array[1]
    • 最后一个索引i=n-1:如果数组长度≥2,需要array[n-1] < array[n-2]
      遍历一遍数组就能把这些候选点找出来,得到按索引排序的列表candidates,O(n)时间。

动态规划+二分查找的高效解法

接下来我们用动态规划来求最大和的子序列,同时利用候选点的性质优化复杂度:

关键转化:把条件1变成可快速判断的形式

条件1要求相邻选中点a和b之间的区间和大于array[a]+array[b],用前缀和转化一下:

sum(a+1..b-1) = prefix_sum[b] - prefix_sum[a+1] > array[a] + array[b]

整理后得到:

prefix_sum[b] - array[b] > prefix_sum[a] + 2*array[a]

我们给每个候选点ci定义两个值:

  • val[i] = prefix_sum[ci] + 2*array[ci](对应右边的式子)
  • target[i] = prefix_sum[ci] - array[ci](对应左边的式子)
    并且因为候选点是局部极小值,val数组是严格递增的(推导:每个候选点ci的下一个元素array[ci+1] > array[ci],导致val[i+1]必然大于val[i])。

动态规划计算

  • 初始化dp数组:dp[i]表示以候选点ci结尾的满足条件的子序列的最大和。如果ci能作为起始点(满足条件2:array[ci] > prefix_sum[ci]),那么dp[i] = array[ci],否则设为负无穷(表示无法以它开头)。
  • 维护max_dp数组:max_dp[i]是dp[0..i]中的最大值,用来快速找到前面能和ci配对的最优子序列。
  • 遍历每个候选点ci(从第2个开始):
    因为val是严格递增的,我们可以用二分查找快速找到最大的索引m,使得val[m] < target[i](也就是所有能和ci满足条件1的前驱候选点)。然后dp[i] = max(dp[i], max_dp[m] + array[ci]),最后更新max_dp。

找到最优解

最后遍历所有能作为终点的候选点(满足条件3:array[ci] > suffix_sum[ci]),取它们的dp[i]最大值就是答案。如果没有这样的点,再检查是否有单个候选点同时满足条件2和3,实在没有就说明不存在符合要求的子序列。

关于O(n)复杂度的可能性

这个解法的总时间复杂度是O(n + k logk),其中k是候选点数量(最多等于n),最坏情况下是O(n logn)——这已经比指数级解法高效太多了。

那能不能降到严格的O(n)?遗憾的是,对于任意严格正元素的数组,很难做到:因为target[i]的值不一定单调,我们没法用双指针线性遍历找到符合条件的前驱候选点,必须依赖二分查找的O(logk)开销。只有当数组有特殊性质(比如target[i]单调递增)时,才能用双指针把时间压到O(n),但这不是通用情况。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:36:05