104. 二叉树的最大深度 (Easy)

专题归类: 05-二叉树 LeetCode 链接: https://leetcode.cn/problems/maximum-depth-of-binary-tree/


在线做题: 写 Python 代码并运行 · Java 跳转 LeetCode

题目描述

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

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

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:3

示例 2:

输入:root = [1,null,2]
输出:2

提示:

  • 树中节点数量在 [0, 10^4] 范围内
  • -100 <= Node.val <= 100

题目详细分析

  • 数据范围含义: 节点数最多 10000,递归深度可能达到 10000,某些语言可能需要考虑栈溢出(Python 默认递归深度约 1000,可能不够)。建议用迭代法或设置 sys.setrecursionlimit
  • 输入输出特征: 输入为根节点,输出为整数(深度)。根节点自身算 1,空树返回 0。
  • 边界条件: root = None 返回 0(空树深度为 0);单节点返回 1。
  • 核心约束: 深度定义是节点数(有的定义是边数,本题明确是节点数)。
  • 隐藏条件: 这是二叉树的「Hello World」问题,几乎所有后续二叉树问题的解法基础。

小白版直白理解

就像测量一棵树的高度——从树根(地面)到最高的那片叶子的层数。如果树只有一根主干没有枝叶,高度就是 1(只有树根自己)。如果左边长到 3 层,右边长到 5 层,那树的高度就是 5(取高的那一边)。


解题思路

思路一:后序递归 / 分解法(推荐)

核心思想: 一棵树的最大深度 = max(左子树的最大深度, 右子树的最大深度) + 1(加上根节点这一层)。

为什么用后序? 因为要知道当前节点的深度,必须先知道左右子树的深度——这就是典型的「后序位置」:先处理左右子树得到结果,再汇总结果计算出当前节点的答案。这种从下往上汇总的方式叫做 分解法(分治思想)。

def maxDepth(root):
    if not root:
        return 0
    # 后序位置:先得到左右子树的结果
    left_depth = maxDepth(root.left)
    right_depth = maxDepth(root.right)
    # 再汇总:当前节点的深度 = 子树的更大深度 + 1
    return 1 + max(left_depth, right_depth)

思路二:BFS 层序遍历

用队列逐层遍历二叉树,能遍历多少层,深度就是多少。

为什么用 BFS? 层序天然地按「层」来处理,每处理完一层深度加 1,非常直观。而且不会出现递归栈溢出的风险。

from collections import deque
 
def maxDepth(root):
    if not root:
        return 0
    q = deque([root])
    depth = 0
    while q:
        depth += 1
        # 一口气处理完当前层的所有节点
        for _ in range(len(q)):
            node = q.popleft()
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
    return depth

思路三:前序递归 + 全局变量(回溯法)

在遍历的过程中记录当前深度,每到叶子节点就更新全局最大深度。

为什么能这样做? 前序遍历的特点是「进入节点时就知道当前深度」,配合回溯(返回时深度减 1),可以模拟用「尺子」沿路径量深度。

def maxDepth(root):
    max_d = 0
 
    def traverse(node, depth):
        nonlocal max_d
        if not node:
            return
        # 前序位置:到达一个节点,更新最大深度
        max_d = max(max_d, depth)
        traverse(node.left, depth + 1)
        traverse(node.right, depth + 1)
 
    traverse(root, 1)
    return max_d

易错点

  • 空树返回 0 而不是 None: base case 必须返回 0,很多初学者会忘记这个特判。
  • 递归时忘记 +1: return max(left, right) 是错的,需要加上当前节点这一层,所以是 1 + max(left, right)
  • BFS 法的 depth 递增时机: 在进入 while 循环时就要 depth += 1,而不是在处理完一层之后。
  • 前序法 depth 的初始值: 根节点的深度是 1,所以从 traverse(root, 1) 开始。

框架提炼

后序递归(分解法)通用模板:

def traverse(node):
    if not node:
        return 0  # 返回基础值
    left_result = traverse(node.left)   # 左子树结果
    right_result = traverse(node.right) # 右子树结果
    # 后序位置:用左右子树的结果构造当前节点的答案
    return compute(node, left_result, right_result)

BFS 层序模板:

def bfs(root):
    if not root:
        return 0
    q = deque([root])
    level = 0
    while q:
        level += 1
        for _ in range(len(q)):
            node = q.popleft()
            # 处理当前节点
            if node.left: q.append(node.left)
            if node.right: q.append(node.right)
    return level

关联题目

  • 543-二叉树的直径 — 在计算深度的同时记录左右深度之和,是本题的直接扩展。
  • 110-平衡二叉树 — 判断左右子树深度差是否不超过 1,也是深度计算的应用。
  • 226-翻转二叉树 — 二叉树的基础递归操作,与本题的递归思维同源。