226. 翻转二叉树
一、算法逻辑(逐步通顺讲解思路)
目标是将原二叉树镜像翻转,即:每个节点的左、右子树交换。本算法使用递归方式处理,具体过程如下:
1️⃣ 边界处理
若当前节点为空,直接返回空。这是递归的终止条件,防止访问 None
节点的子节点。
2️⃣ 递归处理左右子树
通过递归分别调用左子树与右子树自身的 invertTree
方法,使得整棵左子树和右子树都先被处理翻转。
注意此时尚未交换它们,仅将左右子树“翻转完毕”的结果暂存。
3️⃣ 交换当前节点的左右子树
当前节点的左右子树翻转完毕后,执行指针交换:root.left, root.right = right, left
。这就是将“左右子树调换位置”的本质步骤。
这一步发生在左右子树递归处理之后,属于后序遍历逻辑:先处理子树,再处理当前节点。
4️⃣ 返回当前节点
处理完当前节点后,返回自身作为翻转后的根节点,用于上一层的递归拼接。
✅ 本质总结(逻辑闭环)
整个算法从叶子节点向上,逐步完成左右子树的交换。每个节点都做“翻转自己的左右子树”这一件事,由递归统一调度,最终完成整棵树的翻转。
二、核心点总结
这段代码的核心思想是:
使用 后序遍历 的递归方式,自底向上交换每个节点的左右子树。
-
✅ 后序遍历是关键:必须先处理完子树,再交换;
-
✅ 每个节点只处理一次,处理内容就是“递归子树 + 左右互换”;
-
✅ 属于结构清晰、直觉明确的树形递归模板。
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return root # 如果当前节点为空,直接返回
# 递归翻转左子树和右子树
left = self.invertTree(root.left)
right = self.invertTree(root.right)
# 交换左右子树
root.left, root.right = right, left
# 返回翻转后的当前节点
return root
三、时间复杂度分析
每个节点:
-
访问一次;
-
做一次交换操作(常数级);
总共访问所有 n
个节点:
时间复杂度:O(n),其中
n
为节点总数。
四、空间复杂度分析
主要来源于递归栈的深度:
-
最坏情况下(树退化为链表):递归深度为
n
; -
最好情况(平衡二叉树):递归深度为
log n
;
不使用额外数据结构,空间复杂度为递归深度:
空间复杂度:O(h),其中
h
是树的高度。
✅ 总结一句话
该递归解法利用后序遍历结构,从底向上逐层交换左右子树,在 O(n) 时间和 O(h) 空间内高效地实现了整棵二叉树的镜像翻转。逻辑清晰、递归简洁,是树形操作中典范的递归模板。