题目
给定一个二叉树的根节点 root
,返回 它的 中序 遍历 。
提示:
- 树中节点数目在范围
[0, 100]
内 -100 <= Node.val <= 100
解法1:递归
二叉树具有天然的递归结构,中序遍历是在访问完节点的左子树后且访问右子树前对数据进行操作。代码如下:
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
result.reserve(100); // 由于最多存在100个元素,预先分配充足的空间
inorderTraversal(root, result);
return result;
}
private:
void inorderTraversal(const TreeNode* root, vector<int>& result)
{
if (root == nullptr) {
return;
}
inorderTraversal(root->left, result);
result.push_back(root->val);
inorderTraversal(root->right, result);
}
};
时间复杂度为O(n)
,空间复杂度为O(n)
,执行结果如下:
解法2:迭代
由于二叉树具有天然的递归结构,因此递归代码实现较为简单。若采用迭代的方法,需要借助栈进行处理。在中序遍历中,首先访问左子树,当访问完左子树后,处理数据,然后再继续访问右子树。代码如下:
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result{};
result.reserve(100); // 由于最多存在100个元素,预先分配充足的空间
stack<TreeNode*> buffer{};
// 在访问完左右节点后,需要针对该节点做特殊处理.
// 当重新从栈中弹出节点时,如果该节点的右孩子和prev相等,那么表示其右孩子已经访问过,无需再访问,避免无限循环
TreeNode* prev = nullptr;
// 如果节点为空且栈缓存非空,需要从栈中弹出一个节点进行处理
while ((root != nullptr) || (!buffer.empty())) {
while (root != nullptr) {
buffer.push(root);
root = root->left;
}
// 访问完左子树后,从栈缓存中弹出一个节点,即当前待访问的节点
root = buffer.top();
buffer.pop();
// 如果右孩子为空或者右孩子等于prev,表示右孩子已经访问过
if ((root->right == nullptr) || (root->right == prev)) {
if (root->right == nullptr) {
result.push_back(root->val); // 如果右孩子为空,那么需要将结果进行保存
}
prev = root;
root = nullptr;
} else { // 如果右孩子非空且未访问过,那么需要将结果进行保存
result.push_back(root->val);
buffer.push(root);
root = root->right;
}
}
return result;
}
};
时间复杂度为O(n)
,空间复杂度为O(n)
,执行结果如下: