题目描述:
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。
代码思路:
- 排序: 
- 首先,对 
candidates数组进行排序。排序的目的是为了后续能够方便地处理重复元素,并且有助于提前终止搜索(当当前数字已经大于剩余需要达到的目标值时)。 
 - 首先,对 
 - 初始化结果列表: 
- 创建一个空列表 
ans,用于存储所有满足条件的组合。 
 - 创建一个空列表 
 - 定义回溯函数: 
find(s, use, remain)是一个递归函数,用于寻找所有可能的组合。s是当前搜索的起始索引,用于避免重复使用数组中的同一个元素。use是当前已经选择的数字列表(组合)。remain是当前还需要达到的目标值。
 - 回溯逻辑: 
- 遍历从索引 
s到数组末尾的每个元素。 - 如果当前元素与前一个元素相同(
i > s and candidates[i-1] == candidates[i]),则跳过当前循环迭代,以避免重复组合。 - 如果当前元素等于剩余目标值 
remain,则将当前组合use + [c]添加到结果列表ans中,并返回(结束当前递归路径)。 - 如果当前元素小于剩余目标值 
remain,则递归调用find函数,更新起始索引为i+1(因为当前元素已被使用),更新已使用的数字列表为use + [c],更新剩余目标值为remain - c。 - 如果当前元素大于剩余目标值 
remain,则直接返回(结束当前递归路径,因为后续元素只会更大,无法再达到目标值)。 
 - 遍历从索引 
 - 启动回溯: 
- 调用 
find(0, [], target)开始回溯过程,初始时起始索引为 0,已使用的数字列表为空,剩余目标值为target。 
 - 调用 
 - 返回结果: 
- 最后返回结果列表 
ans,其中包含了所有满足条件的独特组合。 
 - 最后返回结果列表 
 
代码实现:
class Solution:def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:candidates.sort()ans = []def find(s,use,remain):for i in range(s,len(candidates)):c = candidates[i]if i>s and candidates[i-1]==candidates[i]:continueif c == remain:ans.append(use + [c])return              if c < remain:find(i+1,use + [c], remain - c)if c > remain:returnfind(0,[], target)return ans