常见题干剖析
路径的一切相关(关于dfs的细节和实现,已经在2021-10-06 剑指offer2:01~12题目+思路+多种题解的12题进行了细致剖析)无论是图or树的展开和还原要熟练掌握!
先理解一下
以上四个方法都是解决某类问题的不同方法,我先来做个剖析:
- 循环:循环是一种程序结构,用于实现其余三者(其余三者类似于一种算法思想)
- 递归:递归的本质上就是一个栈,递归的顺序关系就是入栈的顺序关系,递归的访问顺序就相当于出栈顺序。
- 迭代:递归的递即相当于迭代的过程,区别在于
- 递归最终将结果返回给最外层函数,而迭代将自身不断传递,直到最内层(实际上迭代中已经没有函数层的意义,这里指的是将不断逼近结果的过程)
- 递归是依靠函数的自身调用实现,而迭代是依靠循环关系实现
- 动态规划:递归的归即相当于动态规划的过程,将递归去往的过程省略,从最内层开始逐步记录,返回。能使用(且有必要)使用动态规划的递归往往具有以下两个特征
- 子结构和递归关系明确,可以从最底层开始,底层回到上层。譬如链表的倒序之所以无法使用动态规划是因为不存在反向指针,机器人的运动范围无法使用动归是因为边界条件比较难明确全部列出。
- 存在子问题的重叠(多次计算)。如果只访问一次实际上动态规划比递归节省不了多少复杂度,多次计算还可以使用“记忆化递归”来实现。
思路分析
当剖析题目确定使用以上某个方法后,分析:
- 我最后需要什么,该逐层的返回什么 来定义函数的返回值
- 接受到下一层的返回值or已经知道上一步算的值,我该做什么 来编写函数主体
- 接受到下一层的返回值or已经知道上一步算的值,我该怎么得到这一步的值 来定义优化子结构or状态转移方程,常常是求和(青蛙跳台阶问题,或的关系),求积(筛子的和,与的关系)
- 边界条件是什么 用来确定递归的终止条件和动态规划的起始条件
涉及题目
- 普通递归/迭代:
- 动态规划:
- dfs,bfs专项:属于很常用的一种题型,和普通题目的最大区别就在于某个结点的下个结点(或者说状态)不止一个,所以如果是迭代,往往需要额外的数据结构来辅助记录,且无法使用动归(无法确定起始条件or回不来)
- 剑指 Offer 13. 机器人的运动范围 - 力扣(LeetCode) (leetcode-cn.com)
- 剑指 Offer 28. 对称的二叉树 - 力扣(LeetCode) (leetcode-cn.com)
- 剑指 Offer 32 - I. 从上到下打印二叉树 - 力扣(LeetCode) (leetcode-cn.com)
- 剑指 Offer 37. 序列化二叉树 - 力扣(LeetCode) (leetcode-cn.com)
- 剑指 Offer 38. 字符串的排列 - 力扣(LeetCode) (leetcode-cn.com)
- 剑指 Offer 55 - I. 二叉树的深度 - 力扣(LeetCode) (leetcode-cn.com)
- 剑指 Offer 55 - II. 平衡二叉树 - 力扣(LeetCode) (leetcode-cn.com)
- 剑指 Offer 68 - II. 二叉树的最近公共祖先 - 力扣(LeetCode) (leetcode-cn.com)