#LC104. 二叉树的最大深度
二叉树的最大深度
你好!我是你的 OI 金牌教练。今天我们来探讨一个树论中的入门级必考题——二叉树的最大深度。
在 NOI 系列竞赛中,树的深度不仅是一个基本属性,它是许多高级算法(如倍增 LCA、树链剖分、平衡树)中维护复杂度的核心指标。
一、 题目描述 (NOI 规范版)
题目名称:二叉树的最大深度 (max_depth_binary_tree) 时间限制:1.0s 内存限制:256MB
【问题描述】 给定一棵二叉树的根节点 ,请你计算该二叉树的最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 (注:叶子节点是指没有子节点的节点。)
【输入格式】 输入文件包含多行,描述二叉树的结构: 第一行一个整数 ,表示节点总数。 接下来的 行,每行描述一个节点的信息:首先是该节点的值 ,然后是该节点的左子节点编号 ,最后是右子节点编号 。 (注:节点编号从 0 到 ,根节点固定为 0。如果子节点不存在,则编号为 -1。如果 ,则表示空树。)
【输出格式】 输出一个整数,表示二叉树的最大深度。
【样例 1 输入】
5
3 1 2
9 -1 -1
20 3 4
15 -1 -1
7 -1 -1
【样例 1 输出】
3

【样例 2 输入】
2
1 -1 1
2 -1 -1
【样例 2 输出】
2
【数据范围】
- 节点总数
- 节点值在 之间
二、 预备知识点
- 二叉树结构:理解左子树、右子树以及叶子节点的概念。
- DFS (深度优先搜索):利用递归从上往下探索路径。
- 分治思想:整棵树的高度 = 1 + max(左子树高度, 右子树高度)。
- BFS (广度优先搜索):利用队列按层遍历,层数即为深度。
三、 启发式思维导图:草稿纸上的推理
拿出一张草稿纸,我们一起来推导这个过程:
1. 递归思维 (自底向上)
画出一个简单的三层二叉树:
- 看到根节点时,我想:如果我知道左边多高,右边多高,那我就选高的那个加 1 就可以了。
- 于是我问左儿子:“你多高?”
- 左儿子如果没孩子,他说:“我这只有 1 层”。
- 递归的终点:如果这个位置根本没有节点(空),那高度就是 0。
2. 迭代思维 (自顶向下)
- 想象往树根注水,水按层流下。
- 第一层流完,深度计为 1。
- 把第一层产生的所有儿子放进“待处理”名单,这就是第二层。
- 只要名单不为空,深度就加 1。
3. 复杂度预估
- 时间复杂度:每个节点必须看一遍,所以是 。
- 空间复杂度:
- 递归取决于树的高度。最坏情况(树变成了一条链)是 。
- 迭代取决于树的最宽处(队列的大小),最坏情况也是 。
四、 算法思路提示 (伪代码流程图)
在 NOI 竞赛中,递归实现最为简洁,迭代实现最为稳健。
方案 A:递归 DFS (分治法)
graph TD
Start(开始 DFS node) --> CheckNull{node 编号是否等于 -1}
CheckNull -- 是 --> ReturnZero(返回 0)
CheckNull -- 否 --> RecurseLeft(递归计算左子树深度 LeftH)
RecurseLeft --> RecurseRight(递归计算右子树深度 RightH)
RecurseRight --> Calc(取 LeftH 与 RightH 的最大值并加 1)
Calc --> ReturnVal(返回计算结果)
方案 B:迭代法 (BFS 层序遍历)
graph TD
Start(开始 BFS) --> CheckEmpty{n 是否为 0}
CheckEmpty -- 是 --> Ret0(返回深度 0)
CheckEmpty -- 否 --> Init(初始化队列 Q 并存入根节点 0)
Init --> SetD(设置 depth 等于 0)
WhileQ{Q 是否为空} -- 否 --> LevelProc(深度 depth 自增 1)
LevelProc --> GetSize(获取当前层节点数量 sz)
GetSize --> ForLoop(循环处理当前层的 sz 个节点)
ForLoop --> Pop(取出队头节点 u)
Pop --> PushChildren(将 u 的左右子节点入队 Q)
PushChildren --> ForLoop
ForLoop -- 循环结束 --> WhileQ
WhileQ -- 是 --> Final(返回 depth)
五、 关键读题技巧:哪里是“解题钥匙”?
- 关键词:最大 (Maximum):
- 这暗示了我们需要在多条路径中寻找极值,通常涉及
max()函数。
- 这暗示了我们需要在多条路径中寻找极值,通常涉及
- 关键词:深度 (Depth):
- 在树中,“深度”和“高度”在求解最大值时逻辑是一致的。记住核心公式:
H = max(H_left, H_right) + 1。
- 在树中,“深度”和“高度”在求解最大值时逻辑是一致的。记住核心公式:
- 注意 的特判:
- LeetCode 和 NOI 都非常看重边界条件。空树的深度是 0,这是最容易漏掉的测试点。
- 输入格式的差异:
- LeetCode 习惯直接给指针,而 NOI 习惯给编号或数组。
- 在做题时,先建好结构体数组
struct Node { int l, r; } tree[MAXN];往往比动态申请内存更高效、更安全。
教练寄语: 这道题是通往“树形 DP”的大门。当你理解了如何通过子树的信息汇总出当前节点的信息,你就已经掌握了树形动态规划的核心思想。加油!