根据卡哥的描述,回溯可以处理很多问题, 如下:
组合问题:N个数里面按一定规则找出k个数的集合
切割问题:一个字符串按一定规则有几种切割方式
子集问题:一个N个数的集合里有多少符合条件的子集
排列问题:N个数按一定规则全排列,有几种排列方式
棋盘问题:N皇后,解数独等等
今天是第一天,介绍理论后,就用一道经典的回溯算法帮助记忆模板:
77. 组合
回溯其实是for 循环加上每一个循环中递归寻找答案,所以按照卡哥对递归函数的模板,回溯也有一个类似的“模板”
-
递归函数的返回值
存放每一个路径的一个一维数组 path
一个二维数组res:存储最终结果
n:多少个数字
k: 需要的path里组合的大小
startIndex 开始搜索的Index -
确定终止条件
达到叶子节点: if(path.size() == k){
res.add(path);
return;
} -
单层递归
//单层搜索
for (int i = startInd, i <= n; i++){
//添加该节点到path,
path.add(i);backtraking (n,k, i +1);
//回溯的过程
path. remove(size() - 1)
}
回溯的那一步还是没有太想明白,把代码贴到这里,二刷的时候如果有更多的体会再补充
class Solution {
List<Integer> path = new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
backtracking(n, k , 1);
return res;
}
private void backtracking(int n, int k, int startIndex){
if (path.size() == k) {
res.add(new ArrayList<Integer> (path));
return;
}
for (int i = startIndex; i <= n; i++){
path.add(i);
backtracking(n, k, i + 1);
//backtarcking
path.remove(path.size() - 1);
}
}
}