算法学习(十六)递归回溯

递归回溯

1. 概念

站在回溯树的一个节点上,你只需要思考 3 个问题:

1、路径:也就是已经做出的选择。

2、选择列表:也就是你当前可以做的选择。

3、结束条件:也就是到达决策树底层,无法再做选择的条件

result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return
    
    for 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择

典型的 DFS 但是没有回溯的题目:17. 电话号码的字母组合

2. 解题技巧(我的总结)

1> 使用哈希表存储答案,使用mark标记已访问的防止重复搜索,状态较少(<32)时用一个int即可

题目说明实现
464. 我能赢吗使用int记录已选数字我的提交
1387. 将整数按权重排序使用int记录已计算过的我的提交
1361. 验证二叉树记录每个节点为根时其下的节点数目,直到等于n我的提交
2745. 构造最长的新字符串只要知道每个串剩余数量和前一个串类型,就能唯一确定最大长度,故采用状态压缩dfs我的提交

2> 岛屿问题:曼哈顿距离,广度优先搜索,某一性质(边界)扩散,通过更改标记防止重复搜索

题目说明实现
934. 最短的桥两岛屿使用不同的标记,bfs扩散岛屿1的面积直至和岛屿2相遇我的提交
1020. 飞地的数量从边界扩散,剩余的是有效的1我的提交
1034. 边界着色dfs,是边界标记为-1,不是标记为0,(不是边界 :4个方向的val=target/0/-1的数量==4)我的提交
1254. 统计封闭岛屿的数目边缘的0开始扩散并标志为1,接着深度优先搜索所有独立岛屿我的提交
1765. 地图中的最高点预处理所有的格子标记为-1,大于等于0代表格子被访问了,从睡眠水面扩散高度,每轮增加1我的提交
2658. 网格图中鱼的最大数目sum(x,y) 递归找到所有相邻的水域,每次访问某一水域后都将其至为0防止回头我的提交

3> 二叉树技巧
只考虑根节点 (先考虑根节点为nil,再考虑和根节点的关系,递归到下一层)
使用map记录父节点

题目说明实现
669. 修剪二叉搜索树根节点不在区间内/在区间内两种情况我的提交
623. 在二叉树中增加一行根节点在新层 前两层以上/前一层/新层 三种情况我的提交
863. 二叉树中所有距离为 K 的结点记录父节点,考虑下面的后再向上考虑每个父节点我的提交
971. 翻转二叉树以匹配先序遍历预处理统计每个节点下的节点数目,从而对数组划分我的提交
652. 寻找重复的子树二叉树的序列化我的提交
1443. 收集树上所有苹果的最少时间当前节点time = sum(每个子节点time+2)我的提交
124. 二叉树中的最大路径和递归每个根节点往下的最长路径长度,过程记录每个根节点+左右子树的最大长度我的提交
2925. 在树上执行操作以后得到的最大分数要么只保留根节点 要么拿走根同时保证所有孩子递归满足题意我的提交
面试题 04.05. 合法二叉搜索树记录三个值:是否二叉搜索树、最小值、最大值,输入必须是非nil的,防止极端数据我的提交

4> 棋盘问题,三步:
递归终止,存储答案
遍历当前位置所有合法解,进入下一位置
当前位置无合法解,回退,撤销一切更改

题目说明实现
51. N 皇后从上往下为每一行选择Q位置我的提交
1391. 检查网格中是否存在有效路径使用4维特征记录每种街道的上下左右可行性我的提交
1905. 统计子岛屿ps (每访问一个节点就更改其值以去重)我的提交

5> 降低搜索空间,从排序、忽略顺序、只考虑奇偶性、对实体分类等方面简化

题目说明实现
672. 灯泡开关 Ⅱ只考虑每组灯泡被按了奇偶次,灯泡可以分成4组我的提交
473. 火柴拼正方形降序排列降低后面的枚举次数我的提交

6> 深度优先套路
dfs(env,pos,mark):
if mark[pos] return
else{
所有合法的下一位置nextPos:
处理环境
dfs(env,nextPos,mark)
恢复环境
}

题目说明实现
841. 钥匙和房间深度优先每个房间我的提交

7> 预处理条件,使用map形式方便查找下一合法位置

题目说明实现
851. 喧闹和富有map记录比每个用户有钱的直接用户我的提交
690. 员工的重要性map记录比每个id对应的实体我的提交
753. 破解保险箱map记录比每个可能的钥匙,通过每次在字符串后面添加一位,搜索直至所有key都出现我的提交
756. 金字塔转换矩阵map记录每个二元组上面能放的合法字符我的提交
1042. 不邻接植花map记录比每个花园的邻居我的提交
2368. 受限条件下可到达节点的数目nexts记录每个节点邻居,visited记录受限/已访问节点我的提交

8> 利用二叉树性质,转换、简化题目问题为可以递归的问题

题目说明实现
1530. 好叶子节点对的数量题意->求解所有树枝节点的合法路径->递归记录每个节点到旗下叶子的路径长度我的提交
1559. 二维网格图中探测环dfs中两个分支之间不会产生相连->dfs找环我的提交
652. 寻找重复的子树二叉树的序列化我的提交
2385. 感染二叉树需要的总时间二叉树一个节点将树分成三个部分互不相连 -> (dfs 邻居时间的最大值) + 1我的提交

3. 更多练习

3.1 子集型回溯
题目说明题解
78. 子集和 LC.39 类似,按照 begin 为起点遍历回溯就可以通过
90. 子集 II在 LC.78 的基础上有重复元素的考虑,和 LC.40 类似的剪枝 🔥通过
131. 分割回文串枚举字符之间的逗号,按照 idx 顺序回溯,判断回文通过
698. 划分为k个相等的子集抽象成 k 个桶,每个桶的容量为子集和大小通过
473. 火柴拼正方形和 LC.698 一模一样,抽象成 4 个桶通过
2305. 公平分发饼干k 个桶,但是桶大小未知,从大到小DFS回溯通过
854. 相似度为 K 的字符串DFS 回溯,剪枝,有点难…通过
1255. 得分最高的单词集合参考灵神的子集型回溯,选或不选的思想,注意恢复现场 🔥0x3F
3.2 组合型回溯
题目说明题解
39. 组合总和组合问题需要按照某种顺序搜索:每一次搜索的时候设置 下一轮搜索的起点 begin,也可以排序之后加速剪枝通过
40. 组合总和 II和 LC.39 区别是这个有重复元素,需要去掉当前层(for循环中)第二个数值重复的节点 🔥剪枝
77. 组合和 LC.39 类似,按照 begin 为起点遍历然后回溯就可以,剪枝:剩余元素个数需要多余 k通过
216. 组合总和 III和 LC.40 类似,这题没有重复元素,两个剪枝:小于最小的 || 大于最大的 🔥0x3F
22. 括号生成直接 DFS 思路(选或不选)更简单,比较剩余左右括号数量剪枝LWW
3.3 排列型回溯
题目说明题解
46. 全排列回溯入门问题,无重复元素的排列问题通过
47. 全排列 II去重是关键,排序比较,上一个相同的元素撤销之后再剪枝 🔥剪枝图
51. N 皇后第 row 行填入 path[row] 这个数,求 path 满足条件的全排列Carl

4. 参考

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值