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

如何修改DP算法获取数组非连续元素最大和的对应索引?

非连续元素最大和的索引追踪问题

问题背景与现有代码

我实现了一个DP算法计算数组非连续元素的最大和,但发现同类问题都没记录组成最大和的元素索引。原算法如下:

def maxSum(arr):
    sum = [0]*len(arr);
    sum_indices = []
    for i in range(len(arr)):
        if i==0:
            sum[0] = arr[0];
        elif(i==1):
            sum[1] = max(sum[0],arr[1]);
        else:
            sum[i] = max(sum[i-2]+arr[i],sum[i-1]);
            
    return sum[len(arr)-1];

我尝试修改代码以返回索引,但结果不符合预期:

def maxSum(A):
    n = len(A)
    M = [0]*len(A)
    M[0] = A[0]
    I = [None]*len(A)
    if A[0] > A[1]:
        M[1] = A[0]
        I[0] = True
        I[1] = False
    else:
        M[1] = A[1]
        I[0] = False
        I[1] = True
    
    for i in range(2, len(A)):
        if M[i-1] > M[i-2] + A[i]:
            M[i] = M[i-1]
            I[i] = False
        else:
            M[i] = M[i-2] + A[i]
            I[i] = True
            I[i-1] = False
            I[i-2] = True
    indices = []
    print(I)
    for j in range(len(A)):
        if I[j] == True:
            indices.append(j)
    return indices

例如输入maxSum([1,2,3,8,9]),预期返回组成最大和的元素索引[1,3,4](对应元素2、8、9),但实际返回错误的索引列表。

错误原因

正向修改标记数组I时直接覆盖历史状态是核心问题:

  • 当选择M[i-2]+A[i]时,硬改I[i-1]为False、I[i-2]为True,但i-2位置的标记是否选中取决于更早的最优决策,不是当前i的选择能直接决定的。
  • 这种篡改会导致后续循环的标记逻辑完全混乱,最终得到错误的索引集合。

正确解法:反向回溯索引

正确思路是先计算DP数组得到最大和,再从数组末尾反向回溯判断每个位置是否被选中,避免破坏历史状态:

实现步骤

  1. 计算标准DP数组,记录每个位置的最大非连续和;
  2. 从数组最后一位开始反向遍历:
    • 若当前位置i的最大和等于dp[i-2]+arr[i],说明当前元素被选中,加入索引列表后跳转到i-2;
    • 若等于dp[i-1],说明未选中当前元素,跳转到i-1;
    • 处理边界情况(数组长度为1或2);
  3. 反转索引列表得到正序结果。

代码实现

def max_sum_with_indices(arr):
    n = len(arr)
    if n == 0:
        return []
    if n == 1:
        return [0]
    
    # 计算DP数组
    dp = [0] * n
    dp[0] = arr[0]
    dp[1] = max(arr[0], arr[1])
    
    for i in range(2, n):
        dp[i] = max(dp[i-1], dp[i-2] + arr[i])
    
    # 反向回溯索引
    indices = []
    i = n - 1
    while i >= 0:
        if i == 0:
            indices.append(i)
            break
        if i == 1:
            indices.append(1 if dp[1] == arr[1] else 0)
            break
        if dp[i] == dp[i-2] + arr[i]:
            indices.append(i)
            i -= 2
        else:
            i -= 1
    
    # 反转得到正序索引
    return indices[::-1]

测试验证

输入max_sum_with_indices([1,2,3,8,9]),返回[1,3,4],对应元素和为2+8+9=19,是正确的最大非连续和索引。

额外优化

该逻辑支持含负数的数组:当元素为负数时,DP数组会自动选择不选该元素(继承前一位的最大和)。例如输入[-2,1,3,-4,5],返回索引[1,4],对应元素和为6,是最优解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 21:31:01