Leetcode 二叉树 1

题号直达: 94 二叉树的中序遍历 | 104 二叉树的最大深度

LeetCode 94. 二叉树的中序遍历 ↑

题目

给定一个二叉树的根节点 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:
    def inorder(self, root, res):
        if not root:
            return None
        self.inorder(root.left, res)
        res.append(root.val)
        self.inorder(root.right, res)
    
    def inorderTraversal(self, root):
        res = []
        self.inorder(root, res)
        return res

思路解析(解法一)

  • 中序遍历顺序:左子树 → 根结点值 → 右子树,对应递归调用顺序:先 inorder(left),再 append(root.val),再 inorder(right)。
  • 空结点:root 为 None 时直接返回,不再向下递归。
  • 结果列表:由 inorderTraversal 创建 res,传入辅助函数 inorder 统一收集,最后返回 res。
  • 复杂度:每个结点访问一次,时间 O(n),n 为结点数;递归栈深度最坏 O(n)(链状树),平均 O(h),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

class Solution:
    def inorderTraversal(self, root):
        res = []
        stack = []
        while root is not None or stack:
            while root is not None:
                stack.append(root)
                root = root.left
            root = stack.pop()
            res.append(root.val)
            root = root.right
        return res

思路解析(解法二)

  • 核心:用显式栈模拟递归「一路向左」的过程。中序要求先处理完左子树再访问根,因此先把从当前结点沿左孩子一路入栈,直到左子为空。
  • 内层 while root:不断 stack.append(root) 并 root = root.left,等价于递归深入左子树。
  • 弹出与访问:左走到头后 root = stack.pop(),此时该结点无未处理左子,将 root.val 记入 res,再令 root = root.right,转去处理右子树(下一轮可能再次一路向左入栈)。
  • 外层条件:root is not None or stack 表示当前还有子树可走或栈里还有待回溯的结点。
  • 复杂度:时间 O(n),每个结点入栈、出栈各常数次;空间 O(h),栈深最坏 O(n)(链状树),满足进阶「迭代」写法。

代码(Python)解法三:Morris 中序遍历

# 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:
    def inorderTraversal(self, root):
        res = []
        predecessor = None
        
        while root is not None:
            if root.left is not None:
                # predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
                predecessor = root.left
                while predecessor.right is not None and predecessor.right != root:
                    predecessor = predecessor.right
                
                # 让 predecessor 的右指针指向 root,继续遍历左子树
                if predecessor.right is None:
                    predecessor.right = root
                    root = root.left
                # 说明左子树已经访问完了,我们需要断开链接
                else:
                    res.append(root.val)
                    predecessor.right = None
                    root = root.right
            # 如果没有左孩子,则直接访问右孩子
            else:
                res.append(root.val)
                root = root.right
        
        return res

思路解析(解法三)

  • 核心:Morris 遍历利用树中大量 None 的右指针,临时改成指向后继,从而在不使用栈、不递归的情况下回到「父结点」;遍历结束再恢复为 None,故又称线索二叉树思路。
  • 前驱 predecessor:当前 root 若有左子树,则前驱为「从左孩子出发,沿右孩子一直走到尽头」的结点(且 predecessor.right 不能已是当前 root,避免环上误判)。
  • 两种情况:若 predecessor.right is None,说明第一次来到该子树,暂时 predecessor.right = root 建线索,并进入 root.left;若 predecessor.right == root,说明左子树已按中序走完,此时访问 root.val,拆掉线索 predecessor.right = None,再进入 root.right。
  • 无左孩子:当前结点在中序里轮到访问,记入 res 后走右子。
  • 复杂度:时间 O(n)(每个结点被访问常数次,线索建立与拆除摊还);额外空间 O(1)(仅若干指针),优于递归与栈版的空间。

LeetCode 104. 二叉树的最大深度 ↑

题目

给定一个二叉树 root,返回其最大深度。

二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数。

提示

  • 树中节点的数量在 [0, 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 maxDepth(self, root):
        """
        :type root: Optional[TreeNode]
        :rtype: int
        """
        if root == None:
            return 0
        return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1

思路解析(解法一)

  • 递归含义:maxDepth(root) 表示以 root 为根的子树的最大深度(按结点个数计)。
  • 空树:root is None 时深度为 0。
  • 转移:当前树深度 = 左右子树深度的较大值 + 1(根结点本身占一层)。
  • 复杂度:每个结点访问一次,时间 O(n);递归栈最坏 O(n)(链状树),平均 O(h),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:
    def maxDepth(self, root):
        if root is None:
            return 0
        
        queue = deque()
        queue.append(root)
        ans = 0
        
        while queue:
            sz = len(queue)
            while sz > 0:
                node = queue.popleft()
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
                sz -= 1
            ans += 1
        
        return ans

思路解析(解法二)

  • 核心:按层扩展。队列中始终保存当前层的全部结点;每处理完一层,ans += 1,深度即层数。
  • 内层循环:sz = len(queue) 固定本层结点个数,依次 popleft 并把非空左右孩子入队,避免与下一层混在一起。
  • 与递归对比:递归是「先到底再回溯计深度」;BFS 是「横向扫一层层数」,语义直观。
  • 复杂度:每个结点入队、出队各一次,时间 O(n);队列最多存一层的结点,最坏 O(n)(完全二叉树最宽一层),平均 O(w),w 为最大层宽。
posted @ 2026-10-11 23:45  Phier  阅读(2)  评论(0)    收藏  举报