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-翻转二叉树 — 二叉树的基础递归操作,与本题的递归思维同源。