深度优先搜索DFS + 剪枝 | 回溯:力扣39. 组合总和
方法:深度优先搜索DFS + 剪枝 | 回溯
result = []
def backtrack(选择列表,路径):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(选择列表,路径)
撤销选择
# 做选择
将该选择从选择列表移除
路径.add(选择)
# 撤销选择
路径.remove(选择)
将该选择再加入选择列表
解决一个回溯问题,实际上就是一个决策树的遍历过程:
1、路径:也就是已经做出的选择。
2、选择列表:也就是你当前可以做的选择。
3、结束条件:也就是到达决策树底层,无法再做选择的条件。
要注意去重和剪枝,因为一个元素只能取一次,所以向下选择时,要使用backtrack(path,sum_ + candidates[i],i+1),而组合一可以重复使用数字 dfs(path,sum_ + candidates[i],i)
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
#回溯
res = []
n = len(candidates)
candidates.sort()
def backtrack(path,sum_,start):
if sum_ == target:
res.append(path[:])
return
for i in range(start,len(candidates)):
if i > start and candidates[i] == candidates[i-1]: #去重
continue
if sum_ + candidates[i] > target: #剪枝
break
path.append(candidates[i])
backtrack(path,sum_ + candidates[i],i+1)
path.pop()
backtrack([],0,0)
return res
C++实现:
class Solution {
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
// 回溯
vector<vector<int>> res;
vector<int> path;
int start = 0;
int sum = 0;
sort(candidates.begin(),candidates.end());
backtrack(candidates,res,path,sum,start,target);
return res;
}
void backtrack(vector<int>& candidates,vector<vector<int>>& res,vector<int> path,int sum,int start,int target){
if (sum == target){
res.push_back(path);
return;
}
for (int i=start;i<candidates.size();i++){
if (sum + candidates[i] > target){
break;
}
if (i > start && candidates[i] == candidates[i-1]){
continue;
}
path.push_back(candidates[i]);
backtrack(candidates,res,path,sum+candidates[i],i+1,target);
path.pop_back();
}
}
};