一、题目描述
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:2
示例 2:
输入:root = [2,null,3,null,4,null,5,null,6] 输出:5
提示:
- 树中节点数的范围在
[0, 10^5]
内 -1000 <= Node.val <= 1000
二、解题思路
最小深度是指从根节点到最近叶子节点的最短路径上的节点数量。我们可以使用广度优先搜索(BFS)来解决这个问题,因为BFS可以一层层地遍历树,一旦找到叶子节点就可以立即返回该层的深度,这个深度就是最小深度。
具体步骤如下:
1. 如果根节点为空,返回0。
2. 初始化一个队列,将根节点加入队列。
3. 初始化一个变量记录当前的深度,初始为1。
4. 当队列不为空时,进行以下操作:
- 获取当前队列的长度,这个长度表示当前层的节点数。
- 遍历当前层的所有节点,对于每个节点:
- 如果它是叶子节点(即没有左右子节点),返回当前深度。
- 如果它有左子节点,将左子节点加入队列。
- 如果它有右子节点,将右子节点加入队列。
- 当前层遍历完成后,深度加1。
5. 如果遍历完整个树还没有找到叶子节点,返回0(其实这个情况在正常情况下不会发生,因为根节点本身就是叶子节点)。
三、具体代码
class Solution {
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int depth = 1;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if (node.left == null && node.right == null) {
return depth;
}
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
depth++;
}
return depth;
}
}
四、时间复杂度和空间复杂度
1. 时间复杂度
-
初始化队列:将根节点加入队列的时间复杂度是 O(1)。
-
广度优先搜索:在广度优先搜索中,每个节点最多被访问一次。因此,对于 n 个节点的树,时间复杂度是 O(n)。
-
遍历队列:在每一层,我们需要遍历所有节点。在最坏的情况下,树可能是一个完全二叉树,此时每一层的节点数是上一层的两倍。但是,由于我们在找到第一个叶子节点时就会停止搜索,所以实际上我们不会遍历所有的节点。因此,这个操作的时间复杂度也是 O(n)。
-
综上所述,总的时间复杂度是 O(n)。
2. 空间复杂度
-
队列空间:在广度优先搜索中,我们需要一个队列来存储每一层的节点。在最坏的情况下,树可能是一个完全二叉树,此时队列中最多可能存储 n/2 个节点(树的高度为 log(n) 时)。因此,队列的空间复杂度是 O(n)。
-
其他空间:除了队列之外,我们不需要额外的空间来存储节点的信息,因此这部分的空间复杂度是 O(1)。
-
综上所述,总的空间复杂度是 O(n)。
五、总结知识点
-
二叉树的遍历:代码使用了广度优先搜索(BFS)来遍历二叉树的节点。BFS 是一种层序遍历的方法,通常用于在树或图中找到最短路径。
-
队列的使用:在 BFS 中,使用队列来存储每一层的节点。这是一种先进先出(FIFO)的数据结构,保证了节点按照层次顺序被访问。
-
递归和迭代:虽然代码本身没有使用递归,但是 BFS 的逻辑是一种迭代形式的递归思想,即通过循环来迭代地访问每一层的节点。
-
二叉树的定义:代码中使用了
TreeNode
类来定义二叉树的节点,这是二叉树数据结构的基本表示方法。 -
叶子节点的判断:代码中通过检查节点的左右子节点是否都为空来确定一个节点是否是叶子节点。
-
循环和条件语句:代码使用了
while
循环来处理队列中的节点,并使用了if
条件语句来判断节点是否是叶子节点以及是否存在子节点。 -
队列的基本操作:代码中使用了队列的
offer
方法来添加节点到队列末尾,以及poll
方法来从队列头部移除节点。 -
链表和树的关系:虽然代码中没有直接使用链表,但是二叉树的结构本质上是一种特殊的链表,每个节点包含对左右子节点的引用。
-
层次的概念:代码中通过维护一个
depth
变量来跟踪当前遍历的层次(深度),这是计算最小深度的基础。 -
函数定义和返回值:代码定义了一个
minDepth
函数,它接受一个TreeNode
类型的参数,并返回一个int
类型的值,这是 Java 中定义函数和方法的基本格式。
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。