回溯算法:
回溯是很经典的一个算法,什么是回溯,回溯其实是一种暴力枚举的方式,为啥都暴力了还是很经典的一种方法呢,其实是因为有些问题我们能暴力出来就不错了,就别要其他自行车了。
回溯算法能解决什么问题呢?
- 组合问题:N个数里面按一定规则找出k个数的集合
- 排列问题:N个数按一定规则全排列,有几种排列方式
- 切割问题:一个字符串按一定规则有几种切割方式
- 子集问题:一个N个数的集合里有多少符合条件的子集
- 棋盘问题:N皇后,解数独等等
如何理解回溯算法?
回溯法解决的问题都可以抽象为树形结构,因为回溯法解决的都是在集合中递归查找⼦集,
集合的⼤⼩就构成了树的宽度,递归的深度,都构成的树的深度。递归就要有终⽌条件,所以必然是⼀颗⾼度有限的树。我们就称它为N叉树。
我们可以看一下图(网上找的),以便更好理解:
PS:但并不是所有的遍历都是符合要求的,题目都会刁难你,所以我们要选择剪枝,顾名思义就是把树中不符合题目要求的叶子结点所剪掉,来提高算法效率,这会在之后的题目会给大家在讲一下。
题目七十二变,但答题模板千篇一律,回溯算法也有一套模板,很重要,我差不多写了十几道题目都差不多这个框架,屡试不爽。
还有强调一下,我接下来的编程代码都是Python3,但没有太大的差别,所以重要是学会其算法思想,举一反三。
res = []
def backtrack(未探索区域, res, path):
if 满足条件:
res.append(path)
# return # 如果不用继续搜索需要 return
for 选择 in 未探索区域当前可能的选择:
if 当前选择符合要求:
backtrack(未探索区域, res, path+已探索的区域)
for循环可以理解为横向遍历,backtrack递归就是纵向遍历。
leetcode题目:
组合:
排列:
46. 全排列 - 力扣(LeetCode) (leetcode-cn.com) |
47. 全排列 II - 力扣(LeetCode) (leetcode-cn.com) |
分割:
93. 复原 IP 地址 - 力扣(LeetCode) (leetcode-cn.com) |
131. 分割回文串 - 力扣(LeetCode) (leetcode-cn.com) |
子集:
78. 子集 - 力扣(LeetCode) (leetcode-cn.com) |
90. 子集 II - 力扣(LeetCode) (leetcode-cn.com) |
棋盘问题:
37. 解数独 - 力扣(LeetCode) (leetcode-cn.com) |
51. N 皇后 - 力扣(LeetCode) (leetcode-cn.com) |
这是leetcode部分关于回溯算法的问题,大家可以先提前尝试练一下,我也会在接下来的会对部分题目进行解析。能力有限,请勿喷。