Leetcode 二叉树 2
题号直达: 226 翻转二叉树 | 101 对称二叉树 | 543 二叉树的直径
LeetCode 226. 翻转二叉树 ↑
题目
给你一棵二叉树的根节点 root,翻转这棵二叉树,并返回其根节点。
示例图

提示
- 树中节点数目范围在
[0, 100]内 -100 ≤ Node.val ≤ 100
代码(Python)
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def invertTree(self, root):
"""
:type root: Optional[TreeNode]
:rtype: Optional[TreeNode]
"""
if not root:
return None
temp = root.right
root.right = self.invertTree(root.left)
root.left = self.invertTree(temp)
return root
思路解析
- 递归含义:
invertTree(root)返回以root为根的翻转后子树的新根(仍为root,结构已交换左右)。 - 空结点:
root为None时返回None。 - 交换顺序:先用
temp保存原右子,将root.right指向翻转后的左子invertTree(root.left);再将root.left指向翻转后的原右子invertTree(temp)。若先改root.left再递归右子,会丢失原右子指针,故需temp。 - 复杂度:每个结点访问一次,时间 O(n);递归栈最坏 O(n),平均 O(h),h 为树高。
LeetCode 101. 对称二叉树 ↑
题目
给你一个二叉树的根节点 root,检查它是否轴对称。
示例图

提示
- 树中节点数目在范围
[1, 1000]内 -100 ≤ Node.val ≤ 100
进阶:你可以运用递归和迭代两种方法解决这个问题吗?
代码(Python)解法一:递归
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def check(self, p, q):
# p,q都空了,肯定对称了。
if not p and not q:
return True
# p和q有一个没空,肯定没对称。
if not p or not q:
return False
# 只有根节点相同 且 左子树等于右子树 且 右子树等于左子树才对称
return p.val == q.val and self.check(p.left, q.right)
and self.check(p.right, q.left)
def isSymmetric(self, root):
"""
:type root: Optional[TreeNode]
:rtype: bool
"""
return self.check(root.left, root.right)
思路解析(解法一)
- 对称含义:整棵树关于根结点左右镜像——左子树的左 ↔ 右子树的右,左子树的右 ↔ 右子树的左,且对应结点值相等。
check(p, q):比较「应互为镜像」的两棵子树。二者皆空 → 对称;恰有一空 → 不对称;否则要求p.val == q.val,且p的左与q的右对称、p的右与q的左对称。isSymmetric:根结点自身在对称轴上,只需check(root.left, root.right)。(当前提示保证至少 1 个结点;若题面允许空树,需先判if not root: return True。)- 复杂度:每个结点访问一次,时间 O(n);递归栈最坏 O(n),平均 O(h)。
代码(Python)解法二:迭代(队列)
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
from collections import deque
class Solution(object):
def check(self, u, v):
# 创建队列
q = deque()
q.append(u)
q.append(v)
while q:
u = q[0]
q.popleft()
v = q[0]
q.popleft()
if not u and not v:
continue
if (not u or not v) or (u.val != v.val):
return False
q.append(u.left)
q.append(v.right)
q.append(u.right)
q.append(v.left)
return True
def isSymmetric(self, root):
"""
:type root: Optional[TreeNode]
:rtype: bool
"""
return self.check(root, root)
思路解析(解法二)
- 核心:用队列每次取出应互为镜像的一对结点
u、v,比较是否同为空、或同非空且val相等;再把下一层要比较的镜像对按顺序入队:u.left与v.right、u.right与v.left(可包含None)。 - 与解法一入口不同:
isSymmetric调用check(root, root),第一次比较根与自身,随后入队的是(left, right)与(right, left)两对,等价于从轴两侧同步层序展开。 - 双空
continue:两个都是None表示这一侧没有更多结构,跳过即可,不代表整棵树不对称。 - 复杂度:时间 O(n);队列规模最坏 O(n),无递归栈,满足进阶「迭代」要求。
LeetCode 543. 二叉树的直径 ↑
题目
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点 root。
注意:两结点之间路径的长度由它们之间边数表示。
提示
- 树中节点数目在范围
[1, 10^4]内 -100 ≤ Node.val ≤ 100
代码(Python)解法一:遍历每个结点 + 递归求深度(会超时)
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def depth(self, node):
if not node:
return 0
return max(self.depth(node.left), self.depth(node.right)) + 1
def diameterOfBinaryTree(self, root):
"""
:type root: Optional[TreeNode]
:rtype: int
"""
if not root:
return 0
ans = 0
stack = []
while root is not None or stack:
while root is not None:
stack.append(root)
root = root.left
root = stack.pop()
diameter = self.depth(root.left) + self.depth(root.right)
if diameter > ans:
ans = diameter
root = root.right
return ans
思路解析(解法一)
- 想法:对每个结点
root,经过该结点的最长路径长度为「左子树高度 + 右子树高度」(此处depth表示从该子树根到叶子的最长结点数,左右各一段拼起来边数即为depth(left) + depth(right),与题意一致)。 - 遍历方式:用栈做类似中序的 DFS,逐个访问结点并更新全局最大
ans。 - 为何超时:对每个结点调用一次
depth,而depth自身要遍历子树,最坏 O(n);共 n 个结点,总时间 O(n^2)。当 n = 10^4 时量级约 10^8,容易 TLE。
代码(Python)解法二:后序一次遍历(推荐)
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def __init__(self):
self.ans = 0
def diameterOfBinaryTree(self, root):
def depth(node):
if not node:
return 0
L = depth(node.left)
R = depth(node.right)
self.ans = max(self.ans, L + R)
return max(L, R) + 1
depth(root)
return self.ans
思路解析(解法二)
- 核心:在求每个结点高度的后序过程中,顺带用
L + R更新经过该结点的路径边数最大值;每个结点只在其子树高度已知时算一次,每条边只在向上回溯时被统计常数次。 - 复杂度:时间 O(n),空间递归栈 O(h),可通过本题数据范围。

浙公网安备 33010602011771号