第3天:树结构基础
学习目标
- 掌握二叉树的基本概念和性质
- 熟练实现四种遍历方式:前序、中序、后序、层序
- 理解递归和迭代两种实现方式
- 掌握树的基本操作:深度、高度、路径等
二叉树基础概念
二叉树定义
二叉树是每个节点最多有两个子树的树结构,通常子树被称作”左子树”和”右子树”。
二叉树性质
- 第 i 层最多有 2^(i-1) 个节点
- 深度为 k 的二叉树最多有 2^k - 1 个节点
- 叶子节点数 = 度为2的节点数 + 1
二叉树遍历
- 前序遍历:根 → 左 → 右
- 中序遍历:左 → 根 → 右
- 后序遍历:左 → 右 → 根
- 层序遍历:按层从左到右
今日重点题目
1. 二叉树的中序遍历 (Easy)
题目链接: 94. 二叉树的中序遍历
题目描述:
给定一个二叉树的根节点 root ,返回它的 中序遍历 。
解题思路:
中序遍历:左 → 根 → 右
递归实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> result; inorder(root, result); return result; } private: void inorder(TreeNode* root, vector<int>& result) { if (!root) return; inorder(root->left, result); result.push_back(root->val); inorder(root->right, result); } };
|
迭代实现(使用栈):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> result; stack<TreeNode*> stk; TreeNode* curr = root; while (curr || !stk.empty()) { while (curr) { stk.push(curr); curr = curr->left; } curr = stk.top(); stk.pop(); result.push_back(curr->val); curr = curr->right; } return result; } };
|
时间复杂度: O(n)
空间复杂度: O(n)
2. 二叉树的层序遍历 (Medium)
题目链接: 102. 二叉树的层序遍历
题目描述:
给你二叉树的根节点 root ,返回其节点值的层序遍历。 (即逐层地,从左到右访问所有节点)。
解题思路:
使用队列实现层序遍历,每次处理一层。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Solution { public: vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> result; if (!root) return result; queue<TreeNode*> q; q.push(root); while (!q.empty()) { int size = q.size(); vector<int> level; for (int i = 0; i < size; i++) { TreeNode* node = q.front(); q.pop(); level.push_back(node->val); if (node->left) q.push(node->left); if (node->right) q.push(node->right); } result.push_back(level); } return result; } };
|
时间复杂度: O(n)
空间复杂度: O(n)
3. 二叉树的最大深度 (Easy)
题目链接: 104. 二叉树的最大深度
题目描述:
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
解题思路:
递归计算左右子树的最大深度,取较大值加1。
递归实现:
1 2 3 4 5 6 7
| class Solution { public: int maxDepth(TreeNode* root) { if (!root) return 0; return max(maxDepth(root->left), maxDepth(root->right)) + 1; } };
|
迭代实现(层序遍历):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 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(); 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(n)
空间复杂度: O(n)
4. 翻转二叉树 (Easy)
题目链接: 226. 翻转二叉树
题目描述:
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
解题思路:
递归交换左右子树。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution { public: TreeNode* invertTree(TreeNode* root) { if (!root) return nullptr; TreeNode* temp = root->left; root->left = root->right; root->right = temp; invertTree(root->left); invertTree(root->right); return root; } };
|
时间复杂度: O(n)
空间复杂度: O(n)
树遍历总结
前序遍历模板
1 2 3 4 5 6
| void preorder(TreeNode* root, vector<int>& result) { if (!root) return; result.push_back(root->val); preorder(root->left, result); preorder(root->right, result); }
|
中序遍历模板
1 2 3 4 5 6
| void inorder(TreeNode* root, vector<int>& result) { if (!root) return; inorder(root->left, result); result.push_back(root->val); inorder(root->right, result); }
|
后序遍历模板
1 2 3 4 5 6
| void postorder(TreeNode* root, vector<int>& result) { if (!root) return; postorder(root->left, result); postorder(root->right, result); result.push_back(root->val); }
|
层序遍历模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> result; if (!root) return result; queue<TreeNode*> q; q.push(root); while (!q.empty()) { int size = q.size(); vector<int> level; for (int i = 0; i < size; i++) { TreeNode* node = q.front(); q.pop(); level.push_back(node->val); if (node->left) q.push(node->left); if (node->right) q.push(node->right); } result.push_back(level); } return result; }
|
扩展练习
5. 二叉树的前序遍历 (Easy)
题目链接: 144. 二叉树的前序遍历
6. 二叉树的后序遍历 (Easy)
题目链接: 145. 二叉树的后序遍历
7. 对称二叉树 (Easy)
题目链接: 101. 对称二叉树
8. 平衡二叉树 (Easy)
题目链接: 110. 平衡二叉树
学习总结
树问题解题要点
- 递归思维:树问题通常用递归解决
- 边界条件:处理空节点的情况
- 遍历顺序:根据问题选择合适的遍历方式
- 状态传递:在递归中传递必要的信息
递归三要素
- 递归终止条件:什么时候停止递归
- 递归函数功能:函数要做什么
- 递归调用:如何调用自身
常见错误
- 忘记处理空节点
- 递归终止条件错误
- 遍历顺序错误
- 栈溢出(递归过深)
今日收获
- 掌握了二叉树的四种遍历方式
- 理解了递归和迭代两种实现方法
- 学会了基本的树操作
- 建立了树问题的解题思维
明日预告
明天我们将学习树结构进阶内容,包括路径问题、二叉搜索树等更复杂的树问题。
返回周计划 | 上一题:动态规划进阶 | 下一题:树结构进阶