问题描述
给定一个二叉树的根节点 root
,返回其最大深度。二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数。
示例
示例 1
输入:root = [3,9,20,null,null,15,7]
输出:3
解释:从根节点到最远叶子节点的最长路径为 3 -> 20 -> 15
或 3 -> 20 -> 7
,路径长度为 3。
示例 2
输入:root = [1,null,2]
输出:2
解释:从根节点到最远叶子节点的最长路径为 1 -> 2
,路径长度为 2。
方法一:递归法
递归法是一种直观且高效的方法,利用二叉树的递归性质,分别计算左子树和右子树的最大深度,取较大值并加 1。
代码实现
int maxDepth(struct TreeNode* root) {
if (root == NULL) { // 如果根节点为空,直接返回深度为0
return 0;
}
// 递归计算左子树和右子树的最大深度
int leftDepth = maxDepth(root->left);
int rightDepth = maxDepth(root->right);
return (leftDepth > rightDepth ? leftDepth : rightDepth) + 1;
}
代码解析
- 递归终止条件:如果当前节点为空,返回深度为 0。
- 递归逻辑:
- 递归计算左子树的最大深度
leftDepth
。 - 递归计算右子树的最大深度
rightDepth
。 - 返回左右子树的最大深度值加 1(当前节点的深度)。
- 递归计算左子树的最大深度
- 时间复杂度:O(n),其中 n 是二叉树的节点数。每个节点被访问一次。
- 空间复杂度:O(h),其中 h 是二叉树的高度。递归调用栈的深度等于二叉树的高度。
方法二:层次遍历(广度优先搜索)
层次遍历是一种基于队列的广度优先搜索方法,逐层遍历二叉树,计算层数即为最大深度。
代码实现
int maxDepth(struct TreeNode* root) {
if (root == NULL) { // 如果根节点为空,直接返回深度为0
return 0;
}
struct TreeNode** que = malloc(sizeof(struct TreeNode*) * 10000); // 队列
int front = 0; // 队列头部指针
int rear = 0; // 队列尾部指针
int depth = 0; // 当前深度
que[rear++] = root; // 根节点入队
while (front < rear) {
int levelSize = rear - front; // 当前层的节点数
for (int i = 0; i < levelSize; i++) {
root = que[front++]; // 出队
if (root->left) { // 如果有左子节点,入队
que[rear++] = root->left;
}
if (root->right) { // 如果有右子节点,入队
que[rear++] = root->right;
}
}
depth++; // 每处理完一层,深度加1
}
free(que); // 释放队列内存
return depth;
}
代码解析
- 队列初始化:
- 使用指针数组
struct TreeNode** que
模拟队列。 front
指向队列头部,rear
指向队列尾部。
- 使用指针数组
- 层次遍历逻辑:
- 将根节点入队。
- 当队列不为空时,计算当前层的节点数
levelSize
。 - 遍历当前层的所有节点,将其子节点依次入队。
- 每处理完一层,深度加 1。
- 时间复杂度:O(n),其中 n 是二叉树的节点数。每个节点被访问一次。
- 空间复杂度:O(n),队列在最坏情况下可能存储所有节点。
总结
计算二叉树的最大深度可以通过递归或层次遍历实现。递归法代码简洁,适合深度优先搜索;层次遍历法适合广度优先搜索,逻辑清晰,适合理解二叉树的层次结构。