题目描述:
给定一个候选人编号的集合 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]:
continue
if c == remain:
ans.append(use + [c])
return
if c < remain:
find(i+1,use + [c], remain - c)
if c > remain:
return
find(0,[], target)
return ans