方法:深度优先搜索DFS + 剪枝 | 回溯
result = []
def backtrack(选择列表,路径):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(选择列表,路径)
撤销选择
# 做选择
将该选择从选择列表移除
路径.add(选择)
# 撤销选择
路径.remove(选择)
将该选择再加入选择列表
解决一个回溯问题,实际上就是一个决策树的遍历过程:
1、路径:也就是已经做出的选择。
2、选择列表:也就是你当前可以做的选择。
3、结束条件:也就是到达决策树底层,无法再做选择的条件。
每个组合不能有重复数字:backtrack(path,sum_+i,i+1)
剪枝:和大于n,或者路径长度大于k,剪枝
Python实现:
class Solution:
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
res = []
def backtrack(path,sum_,start):
if sum_ > n: #剪枝
return
if len(path) == k and sum_ == n:
res.append(path[:])
return
for i in range(start,10):
if len(path) or sum_ + i > n: #剪枝
break
path.append(i) #做选择
backtrack(path,sum_+i,i+1) #向下选择
path.pop() #撤销选择
backtrack([],0,1)
return res
C++实现:
class Solution {
public:
vector<vector<int>> combinationSum3(int k, int n) {
//回溯
vector<vector<int>> res;
vector<int> path;
int sum = 0,start = 1;
backtrack(k,n,start,sum,path,res);
return res;
}
void backtrack(int& k,int& n,int start,int sum,vector<int> path,vector<vector<int>>& res){
if (sum > n){//剪枝
return;
}
if (path.size() == k && sum == n){
res.push_back(path);
return;
}
for (int i = start;i <= 9;i++ ){
if (path.size() > k || sum + i > n){ //剪枝
break;
}
path.push_back(i); //做选择
backtrack(k,n,i+1,sum+i,path,res); //向下选择
path.pop_back(); //撤销选择
}
}
};