题目描述
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
思路与算法
这个问题自然是递归的,因为反转一棵树涉及到反转它的子树。
让 f(node) 是一个函数,用于反转以 node 为根的二叉树。如果 node 有左子树 L 和右子树 R,那么根据定义,反转以 node 为根的树是通过首先反转右子树 R 得到 f®,反转左子树 L 得到 f(L),然后交换这两个反转后的子树。用公式表示,我们可以写为:
f(node)=Node(node.val,left=f(node.right),right=f(node.left))
- Base Case: 如果当前节点是 None ,那么没有什么可以反转的,因此我们返回 None
- 递归步骤:对于每个节点
- 递归地反转它的左子树
- 递归地反转它的右子树
- 交换这两个反转的子树
代码
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:if not root:return Noneinverted_left = self.invertTree(root.right)inverted_right = self.invertTree(root.left)root.left = inverted_leftroot.right = inverted_rightreturn root
总结
假设你有一个大盒子,里面装着一个小盒子,小盒子里又装着更小的盒子……一直到最小的盒子里什么都没有。每个盒子的结构都和大盒子一样,只不过尺寸变小了。解决问题的时候,你可以先解决最小盒子的问题,再一层一层往外解决,这就是递归的做法。
递归就是类似这种“在里面还藏着同样的东西”的思想。(同样的东西,或许是同样的函数映射)
简单来说,递归思想就是把一个大问题拆成和原问题很像但更小的问题,一直拆到最简单的时候再一步步合起来解决。这样的方法就叫做递归。
形成递归解决方案/形成递归结构的通用模式
- 确定base case(s):
- 确定可以直接解决的最简单问题实例。
- base case停止递归,防止无限循环
- 在树问题中,base case通常是当前节点为 null(或当你到达叶子节点时)
- 拆解问题
- 确保子问题在性质上与原始问题相似。
- 在二叉树的翻转中,翻转整个树的问题简化为翻转左子树和右子树。
- 定义递归步骤
- 清楚地表达问题的解决方案如何依赖于其子问题的解决方案
- 形式举例:f(node)=Node(node.val,left=f(node.right),right=f(node.left)),这个方程清楚地表达了整个树的解(即 f(node))是如何依赖于其子问题的解(即 f(node.left) 和 f(node.right))。
- 组合子问题的解决方案
- 例如:在反转子树后,交换它们以形成反转树。
- 注意
- 不正确或缺失的基例可能导致无限递归或错误的结果
- 确保每个递归调用都是在一个严格更小或更简单的问题实例上