# 回溯算法简介
# 回溯算法重点概括
- 回溯算法在一棵树上做深度优先遍历;
- 需要知道传递引用与「复制」的区别;
- 一开始比较陌生很正常,题目做多了就好了。
本节是对「回溯算法」内容的高度概括,理解这部分内容需要大家完成相关的练习。
# 回溯算法简介
「回溯算法」是解决很多算法问题的常见思想,它也是传统的人工智能的方法,其本质是 在树形问题中寻找解 。
# 回溯算法是在树形问题上执行一次深度优先遍历
重点概括:回溯算法是对题目中所隐含的「树形结构」执行一次 深度优先遍历。
以下是维基百科中「回溯算法」和「深度优先遍历」的定义。
回溯法 采用试错的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案。回溯法通常用最简单的递归方法来实现,在反复重复上述的步骤后可能出现两种情况:
- 找到一个可能存在的正确的答案;
- 在尝试了所有可能的分步方法后宣告该问题没有答案。
深度优先搜索 算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。这个算法会 尽可能深 的搜索树的分支。当结点
v
的所在边都己被探寻过,搜索将 回溯 到发现结点v
的那条边的起始结点。这一过程一直进行到已发现从源结点可达的所有结点为止。如果还存在未被发现的结点,则选择其中一个作为源结点并重复以上过程,整个进程反复进行直到所有结点都被访问为止。
我刚开始学习「回溯算法」的时候觉得很抽象,一直不能理解为什么 递归之后需要做和递归之前相同的逆向操作,在做了很多相关的问题以后,我发现其实「回溯算法」与「 深度优先遍历 」有着千丝万缕的联系。
# 树形问题
提示:做对这一类问题,通过题目中给出的一个简单的例子,在草稿纸上 画出题目中隐藏的树形结构图 很重要。
用于搜索一个树形问题的所有解,叫做「回溯算法」,是通过什么样的方式搜索的?是通过 深度优先遍历 的方式搜索的。因此 「回溯算法」和「深度优先遍历」是一回事。
# 搜索与遍历
我们每天使用的搜索引擎帮助我们在庞大的互联网上搜索信息。搜索引擎的「搜索」和「回溯搜索」算法里「搜索」的意思是一样的。
搜索问题的解,可以通过 遍历 实现。所以很多教程把「回溯算法」称为爆搜(暴力解法)。因此回溯算法用于 搜索一个问题的所有的解 ,通过深度优先遍历的思想实现。
# 遍历的实现方式是递归
递归算法能解决的一类典型问题,是具有 树形结构 的问题,即一个问题与一个或者多个规模更小、结构相同的问题之间存在联系,我们称这样的问题具有 递归 关系。
# 「深度优先遍历」有「回退」的过程
因为「深度优先遍历」有「回退」的过程,才需要「状态重置」或者称「撤销选择」,这是「回溯」的意思。
提示:「回溯」是通过一个变量的变化搜索问题的所有解。
# 「回溯算法」的模板代码
网上会有人提供「回溯算法」的模板代码,但其实「回溯算法」需要看问题的树形结构是「二叉树」还是「多叉树」来决定代码应该如何编写。
我的观点依然是:学习算法是不能靠模板来学的,思考、练习和调试非常重要,算法问题很灵活,盲目套模板是个误区。
本节提供的练习大家只要认真完成了,写出回溯算法就很容易了。
# 与动态规划的区别
# 共同点
用于求解多阶段决策问题。多阶段决策问题即:
- 求解一个问题分为很多步骤(阶段);
- 每一个步骤(阶段)可以有多种选择。
# 不同点
- 动态规划只需要求我们评估最优解是多少,最优解对应的具体解是什么并不要求。因此很适合应用于评估一个方案的效果;
- 回溯算法可以搜索得到所有的方案(当然包括最优解),但是本质上它是一种遍历算法,时间复杂度很高。
# 总结
「回溯算法」与「深度优先遍历」都有「不撞南墙不回头」的意思。我个人的理解是:「回溯算法」强调了「深度优先遍历」思想的用途,用一个 不断变化 的变量,在尝试各种可能的过程中,搜索需要的结果。强调了 回退 操作对于搜索的合理性。而「深度优先遍历」强调一种遍历的思想,与之对应的遍历思想是「广度优先遍历」。至于广度优先遍历为什么没有成为强大的搜索算法,我们在题解后面会提。
在「力扣」第 51 题的题解《回溯算法(转换成全排列问题 + 剪枝)- 题解后有相关问题 (opens new window)》 中,展示了如何使用回溯算法搜索
作者:liweiwei1419 链接:https://suanfa8.com/backtracking 来源:算法吧 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。