回溯法就是从根节点也就是要求的结果开始向下遍历,逐渐向下搜素,搜索到没有必要继续搜索的节点就把它剪枝,搜索到满足条件的就把它保存下来。
现在就是怎么让节点生出枝来,以这个题为例,从根节点开始,应该是从给到列表的头开始依次往里添加节点。其他中间节点的时候,由于不能重复添加,就要从未添加的数值里做尝试。为了区分已经添加的数值和未添加的数值可以用一个变量i来记录已经遍历的列表位置。
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
if(not candidates):
return []
n=len(candidates)
candidates.sort()
res=[]
# i记录已经添加的节点
# tmp记录临时的路劲
# target记录当前的目标值
def helper(i,tmp,target):
# 返回可行解
if(target==0):
res.append(tmp)
return
# 剪枝
if(i==n or target<candidates[i]):
return
# 在同一个i和tmp情况下,也就是同一个节点的情况下
# 尝试不同的j
# 因为j >=i所以肯定都是未遍历过的
for j in range(i,n):
# 避免出现重复解
if(j>i and candidates[j]==candidates[j-1]):
continue
# 更新遍历数值位置 和临时路径,目标值
helper(j+1,tmp+[candidates[j]],target-candidates[j])
helper(0,[],target)
return res