给定一个二叉树,返回它的中序 遍历。
题目链接:中文题目;英文题目
我推荐大家把二叉树的三种遍历方式一起看了,对比理解,加深记忆(链接更新中,可先到个人主页查看):
递归方法非常的简单,首先我们先来看看中序遍历的顺序:
可以看到,中序遍历先找到左节点,然后打印当前节点,再找到右节点,所以整个递归访问顺序为:
inorderRecursion(root->left); // 往左走
ans.push_back(root->val); // 加入数组
inorderRecursion(root->right); // 往右走
class Solution {
vector<int> ans;
void inorderRecursion(TreeNode* root) {
if (!root) return;
inorderRecursion(root->left);
ans.push_back(root->val);
inorderRecursion(root->right);
}
public:
vector<int> inorderTraversal(TreeNode* root) {
inorderRecursion(root);
return ans;
}
};
迭代的方法稍微要难一些,我们还是使用列队(Queue)来实现,主要思路和之前说的前序遍历是基本一样的,只是和前序遍历不同,我们要先加入左节点,然后把当前节点放在左节点之后,最后才是右节点。
但是这样做也会遇到一个问题:1之前已经处理过了,之后再遇到1会造成无限循环,所以需要对之前处理过的节点进行修改。我们先简化一下二叉树,深度限制为2,即节点仅有1、2、3;按照上述方法处理,queue的元素为:2、1、3,我们发现2和3不会出现重复处理的问题,因为它们为叶节点,而1因为不为叶节点,所以可以考虑添加左右节点之后,把该节点的左右指针指向空,避免之后重复处理的问题;其他思路和前序遍历保持一致,思路流程图如下图所示:
另外,也可以使用stack来实现,思路差异不大,大家可以自己尝试做做,或者参考这篇文章的代码:Golang iterative solution using a stack with docs. 100% runtime.
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ans;
if (!root) return ans;
queue<TreeNode*> q;
q.push(root);
while (q.size()) {
TreeNode* temp = q.front();
q.pop();
int len = q.size();
if (!temp->left && !temp->right) { ans.push_back(temp->val); continue; }
// 中序遍历节点顺序重组
if (temp->left) { q.push(temp->left); temp->left = nullptr; }
q.push(temp);
if (temp->right) { q.push(temp->right); temp->right = nullptr; }
for (int i = 0; i < len; i++) { q.push(q.front()); q.pop(); }
}
return ans;
}
};