学习路线参考:如何灵活运用递归?【基础算法精讲 10】_哔哩哔哩_bilibili
ps:笔记和代码按本人理解整理,重思路
【如果笔记对你有帮助,欢迎关注&点赞&收藏,收到正反馈会加快更新!谢谢支持!】
上期笔记
二叉树递归学习笔记:最大深度&最小深度,路径总和-CSDN博客
题目1:相同的树
- 思路:比对两个树的对应递归单元是否相同
- 拆解:
- 递归单元:当前节点 & 左子树 & 右子树
- 相同的两个树需要满足的条件:
- 当前节点的值相同 【p.val == q.val】
- 左子树相同【isSameTree(p.left, q.left) == True】
- 右子树相同【isSameTree(p.right, q.right) == True】
- 递归终止:两个树有一个为None就终止(此时就可以知道True/False的结果了)
- 都为None → True
- 只有一个为None → False
- 递归单元:当前节点 & 左子树 & 右子树
- 代码:
class Solution: def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool: if p == None and q == None: # 都为None return True elif p == None or q == None: # 只有一个为None return False else: return p.val == q.val and self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
题目2:对称二叉树
- 思路:对称二叉树(= 左子树和右子树对称) → 转化为类似“相同的树”问题
- 拆解:
- 相同 → 对称
- 当前节点的值相同 【p.val == q.val】(不变)
- 左子树相同【比较p.left, q.left】 → p的左树和q的右树相同【比较p.left, q.right】
- 右子树相同【比较p.right, q.right】 → p的右树和q的左树相同【比较p.right, q.left】
- 相同 → 对称
- 代码:
class Solution: def isSymmetric(self, root: Optional[TreeNode]) -> bool: return self.isSameTree(root.left, root.right) def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool: if p == None and q == None: return True elif p == None or q == None: return False else: # 变化:比较“p.left & q.right” 和 "p.right & q.left" return p.val == q.val and self.isSameTree(p.left, q.right) and self.isSameTree(p.right, q.left)
题目3:平衡二叉树
- 难点:递归要传递什么结果(计算是否平衡需要树的高度;但如果子树已经不平衡了,返回高度信息没有意义)
- 拆解:
- 不平衡条件:|左子树高度 - 右子树高度|> 1
- 每个递归单元要判断:当前的树是否平衡
- 每个递归单元要传递:
- 如果左右子树都平衡:当前树的高度【 max(左子树高度,右子树高度) + 1】
- 任意一个子树不平衡:当前树不平衡的信号【如:-1】
- 二叉树中任意一个子树不平衡,则整棵树就不平衡
- 最后判断是否是平衡二叉树:如返回值是-1,则不平衡;返回值是高度,则平衡
- 代码:
class Solution: def isBalanced(self, root: Optional[TreeNode]) -> bool: def dfs(root): if not root: return 0 left_height = dfs(root.left) right_height = dfs(root.right) # 有任意一个子树不平衡,则整棵树不平衡 if left_height == -1 or right_height == -1: return -1 # 如果子树平衡,判断当前的树是否平衡(决定返回高度,还是不平衡信号-1) if abs(left_height - right_height) >= 2: return -1 else: return 1+max(left_height, right_height) result = dfs(root) return result != -1
题目4:二叉树的右视图
- 难点:如何通过递归确定树的每个深度的最右节点?
- ps:【深度和高度】对同一个二叉树来说,深度和高度相同;但对于这个树上的某个节点,深度为从上往下算(root为0),高度为从下往上算(叶子为0)
- 拆解:
- 二叉树的每个深度一定会有一个值 → 输出结果长度 == 树的深度
- 递归顺序:先左后右【对每个树来说,先经过左子树的所有节点,再到右子树】
- 对同一个深度,“后遇到(右侧节点)的值” 覆盖 “先遇到(左侧节点)的值”
- 代码:
class Solution: def rightSideView(self, root: Optional[TreeNode]) -> List[int]: result = [] def dfs(root, height): if not root: return if height >= len(result): # 第一次遇到当前深度 result.append(root.val) else: # 覆盖同样深度左侧的节点 result[height] = root.val dfs(root.left, height+1) dfs(root.right, height+1) dfs(root, 0) return result