方法1:深度优先搜索DFS + 剪枝(回溯 + 剪枝)
思路:
套用回溯的模板,每次从传入的数字到n开始遍历求解,做选择和撤销选择,典型的回溯问题。另外要加剪枝,
也就是在DFS中先判断传进来的start和之后的数字如果不够构成 k就剪枝。
可以画一个树的图
回溯算法框架:
res = []
def backtrack(路径,选择列表):
做剪枝
if 满足结束条件:
res.append(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径,选择列表)
撤销选择
解决一个回溯问题,实际上就是一个决策树的遍历过程:
1、路径:也就是已经做出的选择。
2、选择列表:也就是你当前可以做的选择。
3、结束条件:也就是到达决策树底层,无法再做选择的条件。
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
#DFS,回溯
res = []
def dfs(start,path): #start是枚举选择的起点 path是当前构建的路径(组合)
if len(path) + n - start + 1 < k: #剪枝
return
if len(path) == k:
res.append(path[:]) #拷贝一份path,推入res
return #结束当前递归
for i in range(start,n+1): #枚举出所有选择
path.append(i) #选择
dfs(i+1,path) #向下继续选择
path.pop() #撤销选择
dfs(1,[])
return res
C++实现:
class Solution {
public:
void dfs(int start,int n,int k,vector<int>& path,vector<vector<int>>&res){//start是枚举选择的起点 path是当前构建的路径(组合)
if (path.size() + n - start + 1 < k){ //剪枝
return;
}
if (path.size() == k){
res.push_back(path); //拷贝一份path,推入res
return; //结束当前递归
}
for (int i = start;i <= n;i++){ //枚举出所有选择
path.push_back(i); //选择
dfs(i+1,n,k,path,res); //向下继续选择
path.pop_back(); //撤销选择
}
}
vector<vector<int>> combine(int n, int k) {
// DFS,回溯
vector<int> path;
vector<vector<int>> ans;
dfs(1, n, k,path,ans);
return ans;
}
};