画图便于理解
不带剪枝版
for循环中dfs(n,k,i + 1,ans,curAns),i + 1标识下一个数从当前选择的数的下一个数开始选择,for循环的条件i<n不带剪枝条
/**
* 深度优先搜索
* @param n 搜索的空间
* @param k 子序列的长度
* @param idx 当前在搜索空间的位置
* @param ans 所有的答案序列
* @param curAns 当前的答案序列
*/
private void dfs(int n,int k,int idx,List<List<Integer>> ans,List<Integer> curAns){
//设置循环终止的条件,子序列的长度达到k了
if(curAns.size() == k){
ans.add(new ArrayList<>(curAns));
return;
}
//进行遍历
for (int i = idx; i < n; i++) {
curAns.add(i + 1);
dfs(n,k,i + 1,ans,curAns);
//回溯回来
curAns.remove(curAns.size() - 1);
}
}
带剪枝版
去除不必要的搜索,比如n=5,k=3,当前的一个子答案选择了4和5,已经没有数了,所以这个子答案一开始就没必要存在
唯一的区别在于for循环的条件,n - k + curAns.size()即n - ( k - curAns.size()), 其中( k - curAns.size())为当前的子答案还需要的数的个数,如果当前的解空间已经没有足够的数循环就可以终止了
/**
* 深度优先搜索
* @param n 搜索的空间
* @param k 子序列的长度
* @param idx 当前在搜索空间的位置
* @param ans 所有的答案序列
* @param curAns 当前的答案序列
*/
private void dfs(int n,int k,int idx,List<List<Integer>> ans,List<Integer> curAns){
//设置循环终止的条件,子序列的长度达到k了
if(curAns.size() == k){
ans.add(new ArrayList<>(curAns));
return;
}
//进行遍历
for (int i = idx; i <= n - k + curAns.size(); i++) {
curAns.add(i + 1);
dfs(n,k,i + 1,ans,curAns);
//回溯回来
curAns.remove(curAns.size() - 1);
}
}
代码
/**
* @author :hodor007
* @date :Created in 2020/11/4
* @description :
* @version: 1.0
*/
public class Solution {
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> ans = new ArrayList<>();
ArrayList<Integer> curAns = new ArrayList<>();
if(n == 0)
return ans;
dfs(n,k,0,ans,curAns);
return ans;
}
/**
* 深度优先搜索
* @param n 搜索的空间
* @param k 子序列的长度
* @param idx 当前在搜索空间的位置
* @param ans 所有的答案序列
* @param curAns 当前的答案序列
*/
private void dfs(int n,int k,int idx,List<List<Integer>> ans,List<Integer> curAns){
//设置循环终止的条件,子序列的长度达到k了
if(curAns.size() == k){
ans.add(new ArrayList<>(curAns));
return;
}
//进行遍历
for (int i = idx; i <= n - k + curAns.size(); i++) {
curAns.add(i + 1);
dfs(n,k,i + 1,ans,curAns);
//回溯回来
curAns.remove(curAns.size() - 1);
}
}
public static void main(String[] args) {
Solution solution = new Solution();
List<List<Integer>> combine = solution.combine(1, 1);
for (List<Integer> integers : combine) {
System.out.println(integers);
}
}
}