在开始讨论如何计算树的高度或深度之前,我们需要先明确几个基本概念。树是一种非线性的数据结构,由节点(node)和边(edge)组成。每个节点可以有零个或多个子节点,但只有一个父节点(根节点除外)。
注意:在数据结构中,"树的高度"和"树的深度"这两个术语有时会被混用,但它们实际上有不同的定义。树的高度是从叶子节点向上计算的,而深度是从根节点向下计算的。
对于二叉树这种特殊的树结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。在本题中,我们需要计算给定二叉树的最大深度,也就是从根节点到最远叶子节点的最长路径上的节点数。
递归是解决树相关问题最直观的方法之一。计算二叉树深度的递归思路可以这样理解:
这个算法本质上是对树进行后序遍历(左-右-根),因为我们需要先知道子树的深度才能计算当前节点的深度。
cpp复制int maxDepth(TreeNode* root) {
if (root == nullptr) {
return 0;
}
int leftDepth = maxDepth(root->left);
int rightDepth = maxDepth(root->right);
return max(leftDepth, rightDepth) + 1;
}
递归解法的时间复杂度是O(n),其中n是树中的节点数,因为我们需要访问每个节点一次。空间复杂度在最坏情况下(树退化为链表)是O(n),平均情况下是O(log n),这取决于树的平衡程度。
提示:虽然递归解法代码简洁,但对于深度非常大的树(比如题目中的n≤10^6),递归可能会导致栈溢出。这是因为每次递归调用都会在调用栈上创建一个新的栈帧,当递归深度过大时就会耗尽栈空间。
对于大规模数据(如题目中的n≤10^6),递归解法可能会因为调用栈过深而导致栈溢出。这时我们需要使用迭代方法来避免这个问题。广度优先搜索(BFS)是一种常用的迭代方法。
BFS使用队列来按层级遍历树节点,具体步骤如下:
cpp复制int maxDepth(TreeNode* root) {
if (root == nullptr) return 0;
queue<TreeNode*> q;
q.push(root);
int depth = 0;
while (!q.empty()) {
int levelSize = q.size();
for (int i = 0; i < levelSize; ++i) {
TreeNode* node = q.front();
q.pop();
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
depth++;
}
return depth;
}
BFS解法的时间复杂度同样是O(n),因为每个节点都会被访问一次。空间复杂度在最坏情况下是O(n),因为队列中最多会存储一层的所有节点(对于完全二叉树,最后一层可能有约n/2个节点)。
除了BFS,我们还可以用显式栈来实现DFS的迭代版本,从而避免递归带来的栈溢出问题。这种方法模拟了递归的调用栈,但使用的是堆内存而不是系统调用栈。
cpp复制int maxDepth(TreeNode* root) {
if (root == nullptr) return 0;
stack<pair<TreeNode*, int>> s;
s.push({root, 1});
int maxDepth = 0;
while (!s.empty()) {
auto [node, depth] = s.top();
s.pop();
maxDepth = max(maxDepth, depth);
if (node->right) s.push({node->right, depth + 1});
if (node->left) s.push({node->left, depth + 1});
}
return maxDepth;
}
优点:
缺点:
| 特性 | 递归DFS | 迭代BFS | 迭代DFS |
|---|---|---|---|
| 代码简洁性 | 高 | 中 | 中 |
| 栈溢出风险 | 高 | 无 | 无 |
| 空间复杂度 | O(n)最坏 | O(n)最坏 | O(n)最坏 |
| 适用场景 | 小规模数据 | 大规模数据 | 大规模数据 |
在实际编程竞赛中,树的输入可能有多种形式:
需要根据题目要求正确解析输入数据并构建树结构。
常见的边界条件包括:
掌握了计算树深度的基本方法后,可以尝试解决以下相关问题:
为了巩固所学知识,建议尝试以下练习:
在实际编程竞赛中,树的问题非常常见。掌握树的基本操作和遍历方法是解决更复杂问题的基础。建议从简单的递归实现开始,逐步掌握迭代方法,最后再学习更高级的树操作算法。