深度优先算法
1. 概念
1、对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次。要特别注意的是,二叉树的深度优先遍历比较特殊,可以细分为先序遍历、中序遍历、后序遍历(我们前面使用的是先序遍历)。
2、不全部保留结点,占用空间少;有回溯操作(即有入栈、出栈操作),运行速度慢。
3、一般无回溯操作,即入栈和出栈的操作,所以运行速度比深度优先搜索要快些
2. 解题技巧(我的总结)
1> 数位DP,求小于N的符合条件的数的个数,注意以下几点:
用一个 target数组 存储N的每一位
用一个 preLimit 变量表示前面的是否处于临界状态,当且仅当preLimit为true且当前位到达target对应位时,nextLimit为true
用一个 pos 表示当前处理到数字的第多少位,pos到len(target)时结束递归
题目 | 说明 | 实现 |
---|---|---|
788. 旋转数字 | dp时用preValid表示前面是否已经含有2569 | 我的提交 |
2376. 统计特殊整数 | 使用一个mark,第i位标记i是否被使用,从而压缩状态 | 我的提交 |
60. 排列序列 | 从左到右递归累计排名 | 我的提交 |
233. 数字 1 的个数 | 使用 +(-)pos*10 + pre1sum 作为key存储中间结果 | 我的提交 |
600. 不含连续1的非负整数 | 只要不限制数字的长度 就可以无视前导0 直接dfs | 我的提交 |
2> 前序、中序、后序遍历,二叉搜索树
题目 | 说明 | 实现 |
---|---|---|
2476. 二叉搜索树最近节点查询 | 中序遍历 + 排序 + 二分查找 | 我的提交 |
538. 把二叉搜索树转换为累加树 | 先右后左遍历二叉搜索树 | 我的提交 |
958. 二叉树的完全性检验 | dfs(root)返回三个值,深度、是否完美、是否完全 | 我的提交 |
987. 二叉树的垂序遍历 | 先dfs一边获取矩阵的宽高,再dfs向对应位置添加元素 | 我的提交 |
1373. 二叉搜索子树的最大键值和 | 返回4个值:树是否合法,树最大值,树最小值,元素和 | 我的提交 |
1519. 子树中标签相同的节点数 | 返回1个数组:记录26个字母的出现次数 | 我的提交 |
1609. 奇偶树 | 记录每层的最近值,dfs可保证每层都是从左到右顺序访问到的 | 我的提交 |
3> 递归分解问题
题目 | 说明 | 实现 |
---|---|---|
282. 给表达式添加运算符 | 分解当前val ± 后续val = target,val再分解为含有多少个* | 我的提交 |
224. 基本计算器 | 用栈预处理获取每个左括号对应右位置,然后 每轮读取 一符号+一数值 | 我的提交 |
761. 特殊的二进制序列 | 特殊串一定是1***0这种形式,相邻交换即冒泡排序,且特殊串的所有特殊字串一定是相邻的 | 我的提交 |
4> 去重
题目 | 说明 | 实现 |
---|---|---|
491. 递增子序列 | 某一位置累积序列acc,遍历后面每个比当前大的元素,使用map防止遍历相同的val | 我的提交 |
5> 反证法递归(假设条件)
题目 | 说明 | 实现 |
---|---|---|
785. 判断二分图 | 假设是二分图,按照定义探索矛盾 | 我的提交 |
6> 搜索所有答案(求最优值)剪枝
题目 | 说明 | 实现 |
---|---|---|
421. 数组中两个数的最大异或值 | 根据二进制建立二叉树 | 我的提交 |
789. 逃脱阻碍者 | 想像成阻碍者能否在吃豆人到达某一位置前到达某一位置,能则剪枝 | 我的提交 |
1593. 拆分字符串使唯一子字符串的数目最大 | 剩余能达到的最大数量小于已有最优数量,则剪枝 | 我的提交 |
1901. 寻找峰值 II | 每次都向周围4个中最大的移动 | 我的提交 |
691. 贴纸拼词 | state记录每个字母剩余个数,选择一个可以使state减小的word,dfs(state) = 1 + dfs(nextState) | 我的提交 |
514. 自由之路 | 缓存 (ring位置,key位置)进行状态压缩,预处理记录每个字符出现的位置列表 | 我的提交 |
7> 预处理条件,简化递归过程
题目 | 说明 | 实现 |
---|---|---|
959. 由斜杠划分区域 | 每个方格分成4个部分,用map存储不同条件下的相邻区域,简化过程 | 我的提交 |
8> 深度优先按序搜索,查找第k个答案
题目 | 说明 | 实现 |
---|---|---|
1415. 长度为 n 的开心字符串中字典序第 k 小的字符串 | 深度优先,按字典序遍历,记录答案排名,到第k个时输出 | 我的提交 |
1718. 构建字典序最大的可行序列 | 深度优先,c从大到小填值,i没使用且,pos和pos+i位置都是空的则可以填入 | 我的提交 |
2182. 构造限制重复的字符串 | 深度优先,优先使用最大的字符,直至没有字符能够使用 | 我的提交 |
3. 更多练习
- 233. 数字 1 的个数:题解
- 面试题 17.06. 2出现的次数:题解
- 600. 不含连续1的非负整数:题解
- 902. 最大为 N 的数字组合
- 1012.至少有 1 位重复的数字
- 1067.范围内的数字计数
- 1397.找到所有好字符串(有难度,需要结合一个知名字符串算法)