🎈回溯算法理论基础
回溯算法的本质是穷举,并不是一个高效的算法,但是有的题必须要用回溯法,如:
- 组合问题:N个数里面按一定规则找出k个数的集合
- 切割问题:一个字符串按一定规则有几种切割方式
- 子集问题:一个N个数的集合里有多少符合条件的子集
- 排列问题:N个数按一定规则全排列,有几种排列方式
- 棋盘问题:N皇后,解数独等等
回溯法的模板:
void backtracking(参数) { if (终止条件) { 存放结果; return; } for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { 处理节点; backtracking(路径,选择列表); // 递归 回溯,撤销处理结果 } }
🎈LeetCode77. 组合
链接:77.组合
给定两个整数
n
和k
,返回范围[1, n]
中所有可能的k
个数的组合。你可以按 任何顺序 返回答案。
List<List<Integer>> result;
List<Integer> path;
public List<List<Integer>> combine(int n, int k) {
result=new ArrayList<>();
path=new ArrayList<>();
backtracking(n,k,1);
return result;
}
public void backtracking(int n,int k,int startIndex){
if(path.size()==k){
result.add(new ArrayList<>(path));
return;
}
for(int i=startIndex;i<=n;i++){
path.add(i);
backtracking(n,k,i+1);
path.remove(path.size()-1);
}
}
✨剪枝优化
List<List<Integer>> result;
List<Integer> path;
public List<List<Integer>> combine(int n, int k) {
result=new ArrayList<>();
path=new ArrayList<>();
backtracking(n,k,1);
return result;
}
public void backtracking(int n,int k,int startIndex){
if(path.size()==k){
result.add(new ArrayList<>(path));
return;
}
for(int i=startIndex;i<=n-k+path.size()+1;i++){ //剪枝
path.add(i);
backtracking(n,k,i+1);
path.remove(path.size()-1);
}
}