二叉树中序遍历
给定一个二叉树的根节点 root ,返回它的 中序 遍历。
思路:
采用自然的递归方式是最简洁的方法,因为我们知道递归、递归就是顺向遍历,然后逆向返回结果的过程,所以很容易的将中序遍历结果存入数组。
下面也给出迭代法以及Morris 中序遍历法。
// 递归
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
// 递归中序遍历
void encounter(TreeNode* root, vector<int>& vec) {
if(!root) return; // 递归基
encounter(root->left, vec);
vec.push_back(root->val);
encounter(root->right, vec);
}
public:
// 返回中序遍历结果
vector<int> inorderTraversal(TreeNode* root) {
if(!root) return vector<int>();
vector<int> res;
encounter(root, res);
return res;
}
};
时间复杂度:O(n)
空间复杂度:O(n)
// 迭代法
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> stk;
while (root || !stk.empty()) {
while (root) {
stk.push(root);
root = root->left;
}
root = stk.top();
stk.pop();
res.push_back(root->val);
root = root->right;
}
return res;
}
};
时间复杂度:O(n)
空间复杂度:O(n)
// Morris 中序遍历
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
TreeNode *predecessor = 0; // 初始化一个树节点
while (root) {
if (root->left) {
// predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
predecessor = root->left;
while (predecessor->right && predecessor->right != root) {
predecessor = predecessor->right;
}
// 让 predecessor 的右指针指向 root,继续遍历左子树
if (predecessor->right == 0) {
predecessor->right = root;
root = root->left;
}
// 说明左子树已经访问完了,我们需要断开链接
else {
res.push_back(root->val);
predecessor->right = nullptr;
root = root->right;
}
}
// 如果没有左孩子,则直接访问右孩子
else {
res.push_back(root->val);
root = root->right;
}
}
return res;
}
};
时间复杂度:O(n)
空间复杂度:O(1)