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

组合总和II问题DFS解法错误排查:为何出现不存在的元素组合?

问题描述

给定候选数集合(candidates)和目标数(target),找出candidates中所有和为target的唯一组合,每个候选数在组合中只能使用一次,且解集不能包含重复组合。

示例1

输入:candidates = [10,1,2,7,6,1,5], target = 8
输出:

[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例2

输入:candidates = [2,5,2,1,2], target = 5
输出:

[
[1,2,2],
[5]
]

约束条件

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30

我的解法及问题

这是一个回溯问题,我采用DFS方法,检查每个子序列及其和来生成结果。为处理重复解问题,我将temp数组排序后以tuple形式存入结果集合result。

该解法在示例1中运行正常,但在示例2中出现异常:输入candidates = [2,5,2,1,2], target = 5时,输出为[[1,2,2],[5],[1,1,2]],而预期输出是[[1,2,2],[5]],出现了输入中不存在的元素组合[1,1,2]。

我的代码如下:

from typing import List

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        def dfs(ind, temp, sum):
            if ind >= n:
                if sum == target:
                    temp.sort()
                    result.add(tuple(temp))
                return
            if sum < target:
                temp.append(candidates[ind])
                sum += candidates[ind]
                dfs(ind + 1, temp, sum)
                temp.pop()
                sum -= candidates[ind]
            dfs(ind + 1, temp, sum)
        temp, n = [], len(candidates)
        result = set()
        dfs(0, temp, 0)
        return result

错误原因排查

你的代码出现错误的核心原因有两个:

  1. 原地修改共享列表导致递归路径混乱
    你在终止条件中使用temp.sort()对列表进行原地排序,但temp是所有递归分支共享的可变列表对象。排序操作会直接改变temp的元素顺序,后续的pop和append操作都会基于这个已排序的列表执行,从而生成不符合输入的错误组合(比如示例2中的[1,1,2],就是因为列表顺序被破坏后,后续递归的元素选择逻辑混乱导致的)。

  2. sum变量的冗余修改无意义
    Python中整数是不可变类型,你对sum执行的+=和-=操作只会修改当前函数栈内的局部变量,不会影响外层递归的sum值,这部分代码完全冗余,还容易造成逻辑混淆。


修正后的代码

优化版本(提前排序+跳过重复元素,无需集合去重)

from typing import List

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        # 提前排序,方便跳过重复元素,减少无效递归
        candidates.sort()
        result = []
        
        def dfs(ind, temp, current_sum):
            if current_sum == target:
                result.append(temp.copy())
                return
            if ind >= len(candidates) or current_sum > target:
                return
            
            # 选择当前元素
            temp.append(candidates[ind])
            dfs(ind + 1, temp, current_sum + candidates[ind])
            temp.pop()
            
            # 跳过所有重复的当前元素,避免生成重复组合
            while ind + 1 < len(candidates) and candidates[ind] == candidates[ind + 1]:
                ind += 1
            # 不选择当前元素,直接跳到下一个不同的元素
            dfs(ind + 1, temp, current_sum)
        
        dfs(0, [], 0)
        return result

保留集合去重的修正版本

如果想保留集合去重的思路,只需将原地排序改为生成新列表,不修改原temp:

from typing import List

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        result = set()
        
        def dfs(ind, temp, current_sum):
            if current_sum == target:
                # 生成新的排序列表,不修改原temp
                result.add(tuple(sorted(temp)))
                return
            if ind >= len(candidates) or current_sum > target:
                return
            
            # 选择当前元素
            temp.append(candidates[ind])
            dfs(ind + 1, temp, current_sum + candidates[ind])
            temp.pop()
            
            # 不选择当前元素
            dfs(ind + 1, temp, current_sum)
        
        dfs(0, [], 0)
        return [list(item) for item in result]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 05:37:34