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),可通过本题数据范围。
posted @ 2026-10-11 23:47  Phier  阅读(3)  评论(0)    收藏  举报