题目描述
给定一个二叉树,返回它的中序 遍历。
示例:
输入: [1,null,2,3]
1
2
/
3
输出: [1,3,2]
题目链接: https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
思路1
使用递归。代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
if(root==nullptr) return {};
vector<int> ans;
inOrder(root, ans);
return ans;
}
void inOrder(TreeNode* root, vector<int>& ans){
if(root==nullptr) return;
inOrder(root->left, ans);
ans.push_back(root->val);
inOrder(root->right, ans);
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(h)
思路2
使用迭代。代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
if(root==nullptr) return {};
vector<int> ans;
stack<TreeNode*> s;
TreeNode* curNode = root;
while(curNode!=nullptr || !s.empty()){
while(curNode!=nullptr){
s.push(curNode);
curNode = curNode->left;
}
curNode = s.top(); s.pop();
ans.push_back(curNode->val);
curNode = curNode->right;
}
return ans;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(n)(最坏情况下)。
思路3
使用迭代。思路2是官方的解法,迭代比较复杂,而且三种遍历之间的写法差别较大。题解中的颜色标记法比较好。使用0,1标记节点是否被访问过:0表示没有被访问,1表示访问过了。算法如下:
- 定义两个栈:节点栈nodeStack和标记栈visit,nodeStack存放节点,标记栈标记nodeStack对应位置的节点是否被访问;
- 将root压入nodeStack,将0压入visit(其实可以理解为将(root, 0)压入一个栈了,这里写成两个栈了);
- 如果nodeStack不为空,执行以下循环:
- nodeStack和visit弹出栈顶元素,获取栈顶节点curNode以及该节点是否访问过;
- 如果该节点访问过(1),则将该节点值加入中序遍历序列中;
- 如果该节点没有访问过(0),则将(curNode->right, 0)(在curNode->right不为空的情况下)、(curNode, 1)、(curNode->left, 0)(在curNode->left不为空的情况下)依次压入两个栈中。
代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
if(root==nullptr) return {};
vector<int> ans;
stack<TreeNode*> nodeStack;
stack<int> visit;
nodeStack.push(root); visit.push(0);
while(!nodeStack.empty()){
TreeNode* curNode = nodeStack.top(); nodeStack.pop();
int hasVisit = visit.top(); visit.pop();
if(hasVisit==0){
if(curNode->right!=nullptr){
nodeStack.push(curNode->right); visit.push(0);
}
nodeStack.push(curNode); visit.push(1);
if(curNode->left!=nullptr){
nodeStack.push(curNode->left); visit.push(0);
}
}else{
ans.push_back(curNode->val);
}
}
return ans;
}
};
这样,对于不同的遍历方法,只需要更改在hasVisit==0情况下,3个节点的入栈顺序即可:
- 先序的遍历顺序是中左右,入栈顺序为右左中;
- 中序的遍历顺序是左中右,入栈顺序为右中左;
- 后序的遍历顺序是左右中,入栈顺序为中右左;
可以看到入栈顺序如遍历顺序相反。
- 时间复杂度:O(n)
- 空间复杂度:O(n)