104. 二叉树的最大深度(Maximum Depth of Binary Tree)

难度:简单 | 主题:二叉树、DFS、BFS

题目

给定一个二叉树 root,返回其最大深度(从根节点到最远叶子节点的路径上的节点数)。

示例

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

思路

先讲个故事:测量楼高

你要测量一栋楼的高度。你不能直接飞到楼顶去量,于是你想了个办法:

每层楼的高度是 1 米,那楼高就是层数」

但等等——这不是一栋规整的大楼,而是一棵倒着长的树形建筑——每层可能有多个分支,你选哪条路?

选最深的那个分支。

这就是二叉树的最大深度:1 + max(左子树深度, 右子树深度)


引导式推导:从手动数到递推公式

场景:手动计算以下树的最大深度

 
      3            ← 第 1 层
 
     / \
 
    9   20         ← 第 2 层
 
       /  \
 
      15   7       ← 第 3 层
 

直观答案:3 层。

从根节点思考

  • 到最远叶子节点的路径 = 3 → 9 → 不,3 → 20 → 15(或 7)才是更深的

  • 怎么确定?算一下右子树的最大深度 > 左子树最大深度

递推公式诞生

 
maxDepth(节点) = 0, 如果节点为空
 
maxDepth(节点) = 1 + max(maxDepth(左子), maxDepth(右子)), 如果节点不为空
 

graph TD

    root["3"] --> a["9"] & b["20"]

    b --> c["15"] & d["7"]

    root -.-> rc["maxDepth(3)<br/>= 1 + max(1,2) = 3 ✅"]

    a -.-> ac["maxDepth(9)<br/>= 1 + max(0,0) = 1"]

    b -.-> bc["maxDepth(20)<br/>= 1 + max(1,1) = 2"]

    c -.-> cc["maxDepth(15)<br/>= 1"]

    d -.-> dc["maxDepth(7)<br/>= 1"]

    style root fill:#ffd700

执行过程(后序遍历视角)

  1. 先算 9:左空(0) + 右空(0) → 1

  2. 算 15:左右空 → 1;算 7:左右空 → 1

  3. 算 20:左(1) 和 右(1) 的最大值是 1,+1 → 2

  4. 算 3:左(1) 和 右(2) 的最大值是 2,+1 → 3

这就是后序遍历:先算左右子树的结果,再计算当前节点。

另一种方法:BFS 层序

“最大深度”也等于”层数”——BFS 每处理一层,深度 +1。两种方法都可以。

解法时间空间适用场景
DFS 递归O(n)O(h)最简洁,推荐首选
BFS 层序O(n)O(w)树特别深时避免栈溢出

代码

 
# DFS 递归(三行,首选)
 
def maxDepth(self, root):
 
    if not root:
 
        return 0
 
    return 1 + max(self.maxDepth(root.left),
 
                   self.maxDepth(root.right))
 
# BFS 层序(树很深时避免递归栈溢出)
 
def maxDepth(self, root):
 
    if not root:
 
        return 0
 
    from collections import deque
 
    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
 

复杂度

指标DFSBFS
时间O(n)O(n)
空间O(h),h 为树高,最坏 O(n)O(w),w 为最宽层节点数

实战考量

频率分析

出现在:一面必考的热身题,约 80% 的树类从这题开始。重点是看你能不能从 DFS 自然过渡到 BFS 解法,以及能不能回答”为什么这本质是后序遍历”。

延伸思考

Q:为什么这是后序遍历?

A:算当前节点的深度前,必须知道左右子树的深度。这符合后序遍历的”左右根”顺序——先算子节点,后算父节点。树的几乎所有”从下往上”的问题都是后序遍历。

Q:最小深度怎么做?

A:minDepth = 1 + min(minDepth(left), minDepth(right)) 吗?。最小深度是到最近叶子节点的距离。如果根有右子树没有左子树,min(1+∞, 1+right) 结果是 ∞(错!),正确答案是 1 + left1 + right,取实际存在的那一侧。

Q:337打家劫舍III 和这题有什么联系?

A:337 是树形 DP,也用后序遍历框架:先算左右子树的偷/不偷收益,再算当前节点。最大深度是树形 DP 的”最小原型”——先算子树结果再算当前节点。

Q:N 叉树的最大深度怎么做?(559 题)

A:遍历所有子节点,取最大深度 +1。1 + max(maxDepth(child) for child in root.children)

Q:递归会栈溢出吗?

A:极端不平衡的树(链表状)递归深度 = n,Python 默认递归限制 ~1000。这时用 BFS 或迭代栈避免溢出。

易错点

  • 空节点返回 0(不是 None)

  • 叶子节点 1 + max(0,0) = 1,正确

  • 不要写成 1 + maxDepth(root.left) + maxDepth(root.right)(会变成求和)

  • 最小深度不能直接套 max 换成 min,需要处理只有一侧子树的情况


生活类比

最大深度 → 测量楼高

你站在一栋奇特的建筑里——不是规整的混凝土楼,而是像一棵倒长的榕树。

你不知道哪条路最长,只能让手下的人分头往上爬,各自报告自己路线的深度。

你在中间汇总:左边爬了 5 层,右边爬了 7 层——那楼高就是 1 + max(5, 7) = 8 层(算上你站的这层)。


相关题目

题目关系
111 二叉树的最小深度同族变体,注意”只有一侧子树”的边界
559 N 叉树的最大深度扩展:从左右两个子节点变成多个子节点
337打家劫舍III进阶:后序遍历框架 + DP 状态转移
110平衡二叉树利用深度概念判断平衡(左右子树深度差 ≤ 1)

→ 返回题单:LeetCode学习路线图 > 五、二叉树

速记卡(面试闪卡)

Q1:一句话讲清「104. 二叉树的最大深度(Maximum Depth of Binary Tree)」到底是什么?

A:求二叉树从根到最远叶子的层数,等于 1 加左右子树深度的最大值。

Q2:题目理解 —— 深度到底指什么? —— 怎么理解?

A:像量一棵倒长的树屋:深度是根到最远叶子的节点数,不是到某固定层。选最深的支路。英文:Maximum Depth。

Q3:核心思路 —— 为什么是后序? —— 怎么理解?

A:像派两人分头爬树各报深度,你取较大的加自己一层:先知子树才知父节点,正是后序遍历。英文:Post-order DFS。

Q4:代码实现 —— 三行递归怎么写? —— 怎么理解?

A:像汇总报告:空节点返回 0,否则 1+max(左深,右深);树太深怕栈溢出就换 BFS 一层层数。英文:DFS / BFS。

Q5:复杂度与实战 —— 最小深度坑在哪? —— 怎么理解?

A:像抄近路:DFS O(n) 时间 O(h) 空间;最小深度不能简单把 max 换 min,要防只有一侧子树。英文:Min Depth Trap。

Q6:核心速记主线有哪些?

  • 最大深度 = 1 + max(左子树深, 右子树深),空节点返回 0

  • 本质是后序遍历:先算子树结果再算当前

  • DFS 三行最简洁;树极深用 BFS 防栈溢出

  • 最小深度不能直接 max 换 min,要处理单侧子树

  • N 叉树同理:遍历所有子节点取最大加一

口诀

A:二叉深量后序先,

左右取大加一巅;

空节点归零为基,

最深一枝定天边。

相关链接