说回溯之前,得先知道dfs,说dfs得知道什么是搜索算法。
最常见,常用的搜素算法:
- 广度优先搜索(bfs:Breadth First Search)
- 深度优先搜索(dfs: Depth First Search)
这两种算法在经典的N叉树遍历算法上有最熟悉不过的应用。
比如使用队列层次遍历二叉树就基于bfs,递归方式的前中后序遍历就基于dfs。
当然dfs和bfs有除此之外更加复杂的应用场景。
对于回溯,我的理解就是基于dfs,深度优先搜索上的一种应用场景。
它的重要特点,也就是它的名字,回溯,回溯在搜索到某一层的某一分支之后,如果不满足条件后,就回退,撤销选择,尝试别的分支,直到找到符合结果。
回溯具体代码实现,主要通过递归来实现,因回溯的特点,其代码大部分有极高的对称性。
深度搜索的话,其实就相当于把所有可能的分支都要走一遍,所以朴素回溯,其时间复杂度一般是指数级别的,因为回退尝试,产生很多中间重复计算。这个时候,就需要合理的剪枝操作,来优化提高程序运行速度。但是剪枝一般不会影响时间复杂的大的量级。
❝回溯的关键字:回退,撤销选择,递归,dfs,剪枝。
分析回溯类题目,画出递归状态树就行,然后分析如何回退,如何剪枝。时间复杂度计算就分析总的递归的时间
回溯的代码模板:
public void dfs(当前路径, 当前层级,选择列表,结果集) {
// 1. 终止条件
if(符合条件) {
当前路径加入结果集
return;
}
// 2. 处理当前层
cur.add(...);
// 3. 下探,递归
dfs(cur,level + 1, 选择列表,结果集);
// 4. 回退,撤销选择
cur.remove(...);
}
分享两篇我认为比较好的回溯文章: