思路来自代码随想录
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
paths = []
path = []
used = [0] * len(candidates)
def backtrack(candidates, target, sum_, start_index):
# Base Case
if sum_ == target:
paths.append(path[:])
return
# if sum_ > target:
# return
for i in range(start_index, len(candidates)):
#剪枝
if sum_ + candidates[i] > target:
return
if not used[i]:
if i>0 and candidates[i] == candidates[i-1] and not used[i-1]:
continue
used[i] = 1
sum_ += candidates[i]
path.append(candidates[i])
backtrack(candidates, target, sum_, i+1)
sum_ -= candidates[i] # 回溯
path.pop() # 回溯
used[i] = 0
candidates.sort()#剪枝
backtrack(candidates, target, 0, 0)
return paths
也可以不维护used数组,只需要修改条件为
if i>start_index and candidates[i] == candidates[i-1]:
以图中第一层搜索第二个节点1为例,第一个1所有的组合已经检索完毕并回溯,现在进入到整个程序第一个for循环中i=1的时候,而start_index是主函数中传入的初始值0(这里和第二层第一个节点1有很大不同是,后者是调用的第二个backtrack函数,传入的start_index是1)
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
paths = []
path = []
# used = [0] * len(candidates)
def backtrack(candidates, target, sum_, start_index):
# Base Case
if sum_ == target:
paths.append(path[:])
return
# if sum_ > target:
# return
for i in range(start_index, len(candidates)):
#剪枝
if sum_ + candidates[i] > target:
return
# if not used[i]:
if i>start_index and candidates[i] == candidates[i-1]:
continue
# used[i] = 1
sum_ += candidates[i]
path.append(candidates[i])
backtrack(candidates, target, sum_, i+1)
sum_ -= candidates[i] # 回溯
path.pop() # 回溯
# used[i] = 0
candidates.sort()#剪枝
backtrack(candidates, target, 0, 0)
return paths