【Leetcode hot 100】104.二叉树的深度
问题链接
104.二叉树的深度
问题描述
给定一个二叉树 root
,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:3
示例 2:
输入:root = [1,null,2]
输出:2
提示:
- 树中节点的数量在
[0, 10^4]
区间内。 -100 <= Node.val <= 100
问题解答
二叉树的最大深度定义为“从根节点到最远叶子节点的最长路径上的节点数”,核心解法围绕深度优先搜索(DFS) 和广度优先搜索(BFS) 展开,以下是两种主流思路的完整实现及解析。
DFS 递归解法(最简洁)
思路原理
利用递归的“分治思想”:
- 终止条件:若当前节点为
null
(空树或叶子节点的子节点),深度为0
; - 递归逻辑:当前节点的深度 = 1(当前节点自身) + 左子树与右子树的最大深度(取两者较大值)。
例如,对于示例输入 [3,9,20,null,null,15,7]
:
- 根节点
3
的左子树(节点9
)深度为1
,右子树(节点20
)深度为2
; - 根节点深度 = 1 + max(1, 2) = 3,与示例输出一致。
完整代码
// 二叉树节点定义(题目已给出,此处为完整性展示)
class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val = val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val = val;this.left = left;this.right = right;}
}class Solution {public int maxDepth(TreeNode root) {// 终止条件:空节点深度为0if (root == null) {return 0;}// 递归计算左、右子树深度,取最大值加1(当前节点)int leftDepth = maxDepth(root.left);int rightDepth = maxDepth(root.right);return Math.max(leftDepth, rightDepth) + 1;}
}
代码优化(一行版)
若追求代码简洁,可将递归逻辑压缩为一行(原理与上述一致):
class Solution {public int maxDepth(TreeNode root) {return root == null ? 0 : Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;}
}
复杂度分析
- 时间复杂度:
O(n)
,每个节点仅被访问一次(递归遍历所有节点)。 - 空间复杂度:
O(h)
,h
为二叉树高度(递归调用栈的深度):- 平衡树:
h = logn
,空间复杂度O(logn)
; - 斜树(最坏情况):
h = n
,空间复杂度O(n)
。
- 平衡树:
BFS 层序遍历解法(非递归)
思路原理
利用“队列”实现层序遍历(按层访问节点):
- 初始化队列,将根节点入队(若根为空,直接返回
0
); - 遍历队列时,记录当前层的节点总数(队列大小),依次弹出当前层节点,并将其左、右子节点入队;
- 每遍历完一层,深度加
1
,直至队列为空(所有层遍历完毕)。
例如,对于示例输入 [3,9,20,null,null,15,7]
:
- 第 1 层:节点
3
→ 深度 = 1; - 第 2 层:节点
9
、20
→ 深度 = 2; - 第 3 层:节点
15
、7
→ 深度 = 3; - 队列空,返回深度
3
。
完整代码
import java.util.LinkedList;
import java.util.Queue;class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val = val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val = val;this.left = left;this.right = right;}
}class Solution {public int maxDepth(TreeNode root) {// 根为空,深度为0if (root == null) {return 0;}// 用队列存储待遍历的节点(LinkedList实现Queue接口)Queue<TreeNode> queue = new LinkedList<>();queue.offer(root); // 根节点入队int depth = 0; // 初始化深度while (!queue.isEmpty()) {int currentLevelSize = queue.size(); // 当前层的节点总数// 遍历当前层的所有节点for (int i = 0; i < currentLevelSize; i++) {TreeNode currentNode = queue.poll(); // 弹出当前节点// 左子节点入队(非空才入队)if (currentNode.left != null) {queue.offer(currentNode.left);}// 右子节点入队(非空才入队)if (currentNode.right != null) {queue.offer(currentNode.right);}}depth++; // 遍历完一层,深度加1}return depth;}
}
复杂度分析
- 时间复杂度:
O(n)
,每个节点仅入队、出队一次,遍历所有节点。 - 空间复杂度:
O(m)
,m
为队列的最大容量(即二叉树最宽层的节点数):- 满二叉树(最坏情况):最宽层节点数约
n/2
,空间复杂度O(n)
; - 斜树(最好情况):最宽层节点数为
1
,空间复杂度O(1)
。
- 满二叉树(最坏情况):最宽层节点数约
两种解法对比
解法 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
DFS 递归 | 代码极简、易理解 | 递归深度过大可能栈溢出 | 树深度较小(如平衡树) |
BFS 层序 | 非递归、无栈溢出风险 | 代码稍长,需维护队列 | 树深度较大(如斜树) |