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

求最大不相邻元素和的回溯法时间复杂度及DP回溯最优解构造

嘿,你的思路完全走对了!先给你确认下你提到的例子:输入列表[1,2,3,4,5]对应的memoization数组确实是[1,2,4,6,9],最大和9也完全正确——毕竟最优解是选1、3、5,加起来刚好9,总不能选4和5(相邻了嘛),这点你没搞错~

接下来咱们把你的回溯思路拆解清楚,再补点细节让它更严谨:

回溯的核心逻辑

你从最大和反向推导选中元素的思路非常高效,时间复杂度是O(N),完美适配动态规划的优化方向。具体可以分成这两步来做:

  1. 定位最大和的位置
    先找到memo数组里的最大值,这里要注意:如果最大值出现多次,得选最右侧的那个位置。比如要是输入是[5,1,1,5],memo数组是[5,5,6,10],最大值10在最后一位,从这里回溯就能找到第一个5和最后一个5的组合;要是输入是[3,2,7,10],memo数组是[3,3,10,13],从最后一位的13回溯,能找到第一个3和最后一个10的组合。

  2. 反向推导选中元素
    拿到最大和max_sum和对应的索引idx后,就可以开始往回找了:

    • 如果idx是0:说明第一个元素就是选中的,直接加到结果里就行。
    • 如果idx是1:看哪个元素更大(要是相等的话选哪个都行),加到结果里。
    • 当idx >=2时:
      • 如果max_sum == a_list[idx] + memo[idx-2]:说明当前元素被选中了,把它放进结果,然后更新max_sum = max_sum - a_list[idx],同时把idx改成idx-2(毕竟不能选相邻元素)。
      • 如果max_sum == memo[idx-1]:说明当前元素没被选中,直接把idx减1继续回溯。

    用你的例子[1,2,3,4,5]演示一遍:

    • 初始max_sum=9,idx=4:9等于5加memo[2](5+4=9),所以选中5,max_sum变成4,idx改成2。
    • 现在max_sum=4,idx=2:4等于3加memo[0](3+1=4),选中3,max_sum变成1,idx改成0。
    • 最后idx=0,选中1,结果就是[5,3,1],反转后就是从左到右的选中顺序[1,3,5]。

补充小细节

  • 如果memo数组里有多个相同的最大值(比如输入[2,1,2,1,2],memo是[2,2,4,4,6]),从最右侧的最大值开始回溯,能完整找到最优解:选第0、2、4位的2,加起来刚好6。
  • 要是你想收集所有可能的最优解(比如有好几个组合都能得到最大和),可以在回溯时加分支判断,但一般情况下咱们只要一个最优解就够了,没必要增加复杂度。

代码示例(Python)

给你写个直观的实现,把动态规划计算和回溯找最优解放一起:

def find_max_non_adjacent_sum(a_list):
    if not a_list:
        return 0, []
    n = len(a_list)
    if n == 1:
        return a_list[0], [a_list[0]]
    
    # 构建memo数组
    memo = [0] * n
    memo[0] = a_list[0]
    memo[1] = max(a_list[0], a_list[1])
    for i in range(2, n):
        memo[i] = max(memo[i-1], memo[i-2] + a_list[i])
    
    max_sum = memo[-1]
    result = []
    idx = n - 1
    
    # 回溯找最优解
    while idx >= 0:
        if idx == 0:
            result.append(a_list[idx])
            break
        if idx == 1:
            if a_list[idx] == max_sum:
                result.append(a_list[idx])
            else:
                result.append(a_list[idx-1])
            break
        if memo[idx] == memo[idx-1]:
            idx -= 1
        else:
            result.append(a_list[idx])
            max_sum -= a_list[idx]
            idx -= 2
    
    # 反转结果得到从左到右的选中顺序
    return memo[-1], result[::-1]

# 测试你的例子
a_list = [1,2,3,4,5]
max_sum, selected = find_max_non_adjacent_sum(a_list)
print(f"最大和: {max_sum}")
print(f"选中的元素: {selected}")
# 输出:
# 最大和: 9
# 选中的元素: [1, 3, 5]

这个代码完全贴合你的思路,跑起来就能得到你想要的结果~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:02:14