视频来源:代码随想录
https://www.bilibili.com/video/BV1cy4y167mM
(递归函数)/(回溯函数):回溯就是递归的过程
回溯搜索法:是纯暴力搜索
例如:
- 组合问题:求字符串1234中的所有大小为2的组合
- 切割问题:求字符串特定切割(成回文子串)方法数量
- 子集问题:求字符串1234中所有的子集
- 排列问题:求字符串1234有顺序的排列
- 棋盘问题:N皇后、解数独等问题
思路:
一般都能看成N叉树
伪代码思路:
Void backtracking(){
If (终止条件){
搜集结果;
return;
}
For(集合元素集){
处理结点;
递归函数;
回溯操作;
}
return;
}
样题:
Leecode 77.组合
题目:给定字符串,求个数为k的所有组合
方法1:k重for循环
方法2:回溯算法
思路:使用二叉树。
取1,剩下234, 取2,得12;
取3,得13;
取4,得14;
取2,剩下34, 取3,得23;
取4,得24;
取3,剩下4, 取4,得34。
代码思路:
- 确定递归函数参数返回值
- 确定终止条件
- 单层递归逻辑
伪代码:
# 一维数组patch
# 二维数组result
# n维数组: 1234
# 组合长度k: 2
Void backtracking(n,k,startindex){
If (patch.size==k){
Return ;
}
For (I = startindex;i<=n;i++){
Patch.push(i)
backtracking(n,k,i+1)
Patch.pop()
}
}
回溯算法的剪枝:
当n=4,k=4时,题目二叉树变为了
单层搜索逻辑剪枝优化:
# 一维数组patch
# 二维数组result
# n维数组: 1234
# 组合长度k:4
Void backtracking(n,k,startindex){
If (patch.size==k){
Return ;
}
# n-(k-patch.size)+1 代表最多(即最极限)可以从数组哪个位置开始
# n=4,k=3,得到值为2,即数组的第2个元素,但是这个地方注意由于push/pop的直接是i,不是i作为索引的数组值,所以使用+1且在for判断时使用<=,而不是<
For (I = startindex;i<=n-(k-patch.size)+1;i++){
Patch.push(i)
backtracking(n,k,i+1)
Patch.pop()
}
}