作为一名经历过无数次算法面试的老手,我完全理解这种"明明做过却还是不会"的挫败感。计算二叉树深度这个看似简单的问题,实际上考察了程序员对递归和树结构的核心理解。今天我们就来彻底拆解这个经典问题,不仅让你记住解法,更要理解背后的思维逻辑。
二叉树的深度(Depth)是指从根节点到最远叶子节点的最长路径上的节点数。注意这个定义中的几个关键点:
举个例子,对于下面这个简单二叉树:
code复制 A
/ \
B C
/
D
深度为3(路径A->B->D),而节点C的深度是2。
递归是解决树问题的天然工具,因为树本身就是递归定义的数据结构。计算深度的递归思路可以分解为:
这个"1+"代表当前节点本身,然后我们比较左右子树的深度,取较大者加上当前节点。这种"分而治之"的策略是树问题中的常见模式。
让我们仔细分析给出的C++实现代码,理解每一行的作用和背后的考量。
cpp复制struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
这是LeetCode标准的二叉树节点定义,包含:
val:节点存储的整数值left和right:指向左右子节点的指针cpp复制int calculateDepth(TreeNode* root) {
if(root==NULL){
return 0;
}
else{
int lmax=calculateDepth(root->left);
int rmax=calculateDepth(root->right);
return 1+max(lmax,rmax);
}
}
逐行解析:
if(root==NULL):处理基准情况,空树深度为0int lmax=calculateDepth(root->left):递归计算左子树深度int rmax=calculateDepth(root->right):递归计算右子树深度return 1+max(lmax,rmax):当前节点深度为左右子树最大深度加1关键理解:这个递归是"后序遍历"(左右根)的形式,因为我们需要先知道子树的深度才能计算当前节点的深度。
为了更直观地理解递归过程,让我们用一个具体例子来跟踪执行:
考虑二叉树:
code复制 1
/ \
2 3
/ \
4 5
递归调用栈的展开过程:
最终结果为3,符合预期。
每个节点都会被访问一次,因此时间复杂度是O(n),其中n是树中的节点数。
空间复杂度取决于递归调用的深度,也就是树的高度:
虽然递归解法简洁,但了解迭代解法也很重要,特别是在处理深度很大的树时避免栈溢出。
cpp复制int calculateDepth(TreeNode* root) {
if(!root) return 0;
queue<TreeNode*> q;
q.push(root);
int depth = 0;
while(!q.empty()){
int size = q.size();
depth++;
for(int i=0; i<size; i++){
TreeNode* node = q.front();
q.pop();
if(node->left) q.push(node->left);
if(node->right) q.push(node->right);
}
}
return depth;
}
| 特性 | 递归解法 | 迭代解法 |
|---|---|---|
| 代码简洁性 | 高 | 中等 |
| 空间复杂度 | O(h)(调用栈) | O(n)(队列) |
| 适用场景 | 一般情况 | 深度特别大的树 |
| 可读性 | 对熟悉递归的人更直观 | 更符合常规思维 |
在实际面试和工作中,我有几点深刻体会:
递归思维需要刻意练习:刚开始会觉得递归很反直觉,但通过大量练习后,会形成"递归直觉"。
测试用例决定代码质量:好的测试用例能发现潜在问题,我通常会测试:
迭代解法作为备选:即使问题明显适合递归,也要准备迭代解法,展示全面的技术能力。
变量命名很重要:像lmax和rmax这样的命名虽然简短,但leftDepth和rightDepth会更清晰,减少理解成本。
复杂度分析要准确:不要笼统地说"递归的时间复杂度",要具体分析递归的次数和每次递归的操作。
最后一个小技巧:在面试中,可以先写出递归解法,然后主动提出"这个解法在最坏情况下可能会导致栈溢出,我还可以用BFS实现一个迭代版本",这会给面试官留下很好的印象。