104. 二叉树的最大深度(简单)
题目:给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
示例:
给定二叉树 [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回深度 3。
解法一:递归(DFS)
cpp
class Solution {
public:
int maxDepth(TreeNode* root) {
if (!root) return 0;
return 1 + max(maxDepth(root->left), maxDepth(root->right));
}
};
解法二:迭代(BFS,层序遍历)
cpp
class Solution {
public:
int maxDepth(TreeNode* root) {
if (!root) return 0;
queue<TreeNode*> q;
q.push(root);
int depth = 0;
while (!q.empty()) {
int size = q.size();
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);
}
++depth;
}
return depth;
}
};
110. 平衡二叉树(简单)
题目:给定一个二叉树,判断它是否是平衡二叉树。
注释:平衡二叉树是指该树所有节点的左右子树高度相差不大于1
示例:
输入:root = [3,9,20,null,null,15,7]
输出:true
输入:root = [1,2,2,3,3,null,null,4,4]
输出:false
解法:自底向上递归(后序遍历)
cpp
class Solution {
public:
bool isBalanced(TreeNode* root) {
return getHeight(root) != -1;
}
private:
int getHeight(TreeNode* node) {
if (!node) return 0;
int left = getHeight(node->left);
if (left == -1) return -1;
int right = getHeight(node->right);
if (right == -1) return -1;
if (abs(left - right) > 1) return -1;
return 1 + max(left, right);
}
};
复杂度:时间 O(n),空间 O(n)(递归栈)。
二叉树遍历详解
二叉树的遍历是指按照某种顺序访问树中的每个节点,确保每个节点被访问一次。常见的遍历方式有四种:前序遍历 、中序遍历 、后序遍历 和层序遍历。
一、后序遍历(Post-order Traversal)
定义 :先访问左子树,再访问右子树,最后访问根节点。
顺序 :左 → 右 → 根
用途:常用于释放树节点、计算树的高度、求表达式树的值等需要先处理子节点再处理父节点的场景。
递归实现:
cpp
void postorder(TreeNode* root) {
if (!root) return;
postorder(root->left);
postorder(root->right);
cout << root->val << " "; // 访问根节点
}
示例树:
1
/ \
2 3
/ \
4 5
后序遍历结果:4 5 2 3 1
二、其他遍历方式
1. 前序遍历(Pre-order Traversal)
- 顺序:根 → 左 → 右
- 用途:复制树、序列化、前缀表达式。
- 结果 (同上树):
1 2 4 5 3
cpp
void preorder(TreeNode* root) {
if (!root) return;
cout << root->val << " ";
preorder(root->left);
preorder(root->right);
}
2. 中序遍历(In-order Traversal)
- 顺序:左 → 根 → 右
- 用途:二叉搜索树(BST)的中序遍历得到有序序列。
- 结果 (同上树):
4 2 5 1 3
cpp
void inorder(TreeNode* root) {
if (!root) return;
inorder(root->left);
cout << root->val << " ";
inorder(root->right);
}
3. 层序遍历(Level-order Traversal)
- 顺序:从上到下,从左到右逐层访问。
- 用途:广度优先搜索(BFS)、求树的最小深度、打印树形结构。
- 结果 (同上树):
1 2 3 4 5
cpp
void levelOrder(TreeNode* root) {
if (!root) return;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode* node = q.front(); q.pop();
cout << node->val << " ";
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
}
三、递归与迭代实现对比
- 递归:代码简洁,但可能因树深度过大导致栈溢出(如退化为链表)。
- 迭代:需手动模拟栈,但可避免递归深度限制,且更容易控制。
例如,前序遍历的迭代实现:
cpp
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> stk;
if (root) stk.push(root);
while (!stk.empty()) {
TreeNode* node = stk.top(); stk.pop();
res.push_back(node->val);
if (node->right) stk.push(node->right);
if (node->left) stk.push(node->left);
}
return res;
}
四、总结
| 遍历方式 | 访问顺序 | 典型应用 |
|---|---|---|
| 前序遍历 | 根 → 左 → 右 | 复制树、序列化 |
| 中序遍历 | 左 → 根 → 右 | BST 排序输出 |
| 后序遍历 | 左 → 右 → 根 | 计算高度、释放树 |
| 层序遍历 | 逐层从左到右 | BFS、最短路径 |
理解这些遍历是解决二叉树问题的基础,例如:
- LeetCode 104 二叉树的最大深度 可以用后序遍历或层序遍历。
- LeetCode 110 平衡二叉树 使用后序遍历自底向上判断高度差。