目录
- 引言
- 二叉树的中序遍历
- 我的解题
- 代码优化
- 更清晰的表述建议:
- 🙋♂️ 作者:海码007
- 📜 专栏:算法专栏
- 💥 标题:【Hot 100】94. 二叉树的中序遍历
- ❣️ 寄语:书到用时方恨少,事非经过不知难!
引言
今天开始二叉树的篇章,继续加油。
二叉树的中序遍历
- 🎈 题目链接:https://leetcode.cn/problems/binary-tree-inorder-traversal/description/?envType=study-plan-v2&envId=top-100-liked
- 🎈 做题状态:
我的解题
二叉树的遍历有四种,分别是前序、中序、后序以及层次遍历。前中后序遍历可以通过递归写出清晰的代码,当然也可以通过栈来写出非递归的代码。然后是层次遍历通过借助队列来实现一层一层的遍历顺序。
下面来解析一下我的代码,本题给出的核心函数是 inorderTraversal
然后函数有一个返回值,这个返回值记录的是二叉树的值。如果我直接将 inorderTraversal
作为一个递归函数来写的话,就需要处理这个返回值,要考虑如何将这个返回值合并。所以为了让记录变得更加方便我新建了一个递归函数 midTraversal
,这个函数没有返回值,但是使用了引用传递来让这个结果合并起来。
class Solution {
public:void midTraversal(TreeNode* node, vector<int>& data){if (!node) return;midTraversal(node->left, data);data.push_back(node->val);midTraversal(node->right, data);}vector<int> inorderTraversal(TreeNode* root) {vector<int> res;midTraversal(root, res);return res;}
};
代码优化
-
递归函数的返回值问题:
- 如果直接让
inorderTraversal
递归调用自身,每次递归都需要合并子树的遍历结果(即处理返回值),这会增加代码复杂度。 - 例如:
vector<int> inorderTraversal(TreeNode* root) {if (!root) return {};auto left = inorderTraversal(root->left); // 需要合并左子树的结果auto right = inorderTraversal(root->right); // 需要合并右子树的结果left.push_back(root->val); // 插入当前节点left.insert(left.end(), right.begin(), right.end()); // 合并右子树return left; // 返回合并后的结果 }
- 这种写法需要频繁合并向量,效率较低(时间复杂度为 O(n^2)),且代码冗余。
- 如果直接让
-
引用传递的优化:
- 通过引入辅助函数
midTraversal
,将结果向量data
通过引用传递,避免返回值合并的问题。 - 递归过程中直接修改同一个
data
向量,无需合并,效率更高(时间复杂度 O(n))。
- 通过引入辅助函数
更清晰的表述建议:
“中序遍历的递归实现需要按左子树->根节点->右子树
的顺序访问节点。如果直接在 inorderTraversal
中递归,每次递归调用会返回一个独立的向量,需要将这些向量合并(如拼接左子树、当前节点、右子树的结果),效率较低。
因此,我引入辅助函数 midTraversal
,通过引用传递一个共享的结果向量 data
。递归过程中,所有节点值直接追加到 data
中,无需合并操作,既简化了代码,又保证了线性时间复杂度。”