回溯法其实与深度优先搜索区别不大,模板也基本上一致,如下:
public void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
77. 组合
下面这个代码是排列,注意排列和组合的区别,排列记录是否访问,组合不用。
ArrayList<Integer> temp = new ArrayList<>();;
List<List<Integer>> res = new ArrayList<>();;
int[] visit;
public void dfs(int n , int k){
if(temp.size()==k){
ArrayList clone = (ArrayList)temp.clone();
res.add(clone);
return;
}
for (int i = 0; i < n ; i++) {
if(visit[i]==0){
visit[i]=1;
temp.add(i+1);
dfs(n,k);
visit[i]=0; //回溯
temp.remove(temp.size()-1); //回溯
}
}
}
public List<List<Integer>> combine(int n, int k) {
visit = new int[n];
Arrays.fill(visit,0);
dfs(n,k);
return res;
}
下面这段是组合,组合是需要记录步数的,即下一次不能包含本次遍历的数。
ArrayList<Integer> temp = new ArrayList<>();;
List<List<Integer>> res = new ArrayList<>();;
public void dfs(int n , int k,int step){
if(temp.size()==k){
ArrayList clone = (ArrayList)temp.clone();
res.add(clone);
return;
}
for (int i = step; i <= n ; i++) {
//横向遍历
temp.add(i);
dfs(n,k,i+1); //纵向遍历,只能取i之后的数
temp.remove(temp.size()-1); //回溯
}
}
public List<List<Integer>> combine(int n, int k) {
dfs(n,k,1);
return res;
}
组合问题的优化剪枝:
剪枝原理:假设n=4,k=4,只有step=1时才有结果,后面的step>1都取不到4个数,因此可以在for循环内判断是否满足数目的要求,从而避免无效搜索。
for (int i = step; i <= n-(k-temp.size()) ; i++) {
//横向遍历优化,留足数目
temp.add(i);
dfs(n,k,i+1); //纵向遍历,只能取i之后的数
temp.remove(temp.size()-1);
}
216. 组合总和 III
class Solution {
List<List<Integer>> res = new ArrayList<>();
ArrayList<Integer> temp = new ArrayList<>();
int sum = 0;
public void dfs(int k, int n, int step) {
if (temp.size() == k && sum == n) {
ArrayList<Integer> clone = (ArrayList<Integer>) temp.clone();
res.add(clone);
return;
}
for (int i = step; i <= 9 ; i++) {
// 优化 9 - (k - temp.size())
if(sum+i>n){
continue;
}
temp.add(i);
sum += i;
dfs(k, n, i + 1);
sum -= i;
temp.remove(temp.size() - 1);
}
}
public List<List<Integer>> combinationSum3(int k, int n) {
dfs(k, n, 1);
return res;
}
}
参考:https://programmercarl.com/0077.%E7%BB%84%E5%90%88%E4%BC%98%E5%8C%96.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC