题目
给定一个二叉树的根节点 root
,返回 它的 中序 遍历 。
示例 1:
输入:root = [1,null,2,3]
输出:[1,3,2]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
提示:
- 树中节点数目在范围
[0, 100]
内 -100 <= Node.val <= 100
解题方法
递归
通过递归调用的方式先后处理左子树、父节点、右子树。
时间复杂度O(n)
,空间复杂度O(logn)
,最劣O(n)
C++代码:/**
* 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 {
public:
void mid_order(TreeNode* p, vector<int>& vec) {
if(p!=NULL) {
if(p->left != NULL) mid_order(p->left, vec);
vec.push_back(p->val);
if(p->right != NULL) mid_order(p->right, vec);
}
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
if(root == NULL) return result;
mid_order(root, result);
return result;
}
};
迭代
使用 栈 记录节点,通过指针前往最左子树,当指针指向节点的左节点为空时,再依次将指针所在节点压入数组,并前往右子树,并继续前往最左子树,重复上述操作。
时间复杂度O(n)
,空间复杂度O(logn)
,最劣O(n)
C++代码:/**
* 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 {
public:
void mid_order(TreeNode* p, vector<int>& vec) {
stack<TreeNode*> nodes;
TreeNode* cur = p;
while(cur != NULL || nodes.size()>0) {
if(cur!=NULL) {
nodes.push(cur);
cur = cur->left;
}
else {
cur = nodes.top();
nodes.pop();
vec.push_back(cur->val); // 父节点
cur = cur->right; // 右子树
}
}
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
if(root == NULL) return result;
mid_order(root, result);
return result;
}
};
Morris 遍历
使用 Morris 遍历,在完成左子树后返回父节点,即当前节点左子树的最右节点的右节点指向当前节点,将父节点压入数组,再处理右子树。当前节点左子树为空时,将当前节点压入数组,并处理右节点。
时间复杂度O(n)
,空间复杂度O(1)
C++代码:/**
* 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 {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
TreeNode *mostright, *cur=root;
if(root == NULL) return result;
while(cur!=NULL) {
mostright = cur->left;
if(mostright!=NULL) {
while(mostright->right != NULL && mostright->right != cur) mostright = mostright->right;
if(mostright->right == NULL) {
mostright->right = cur;
cur = cur->left;
}
else {
mostright->right = nullptr;
result.push_back(cur->val); // 父节点
cur = cur->right; // 右子树
}
}
else {
result.push_back(cur->val);
cur = cur->right;
}
}
return result;
}
};
标记法(二叉树遍历的统一写法)
设置标志位来判别节点是否二次访问,对二次访问的节点压入数组。
时间复杂度O(n)
,空间复杂度O(logn)
,最劣O(n)
C++代码:/** * 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 { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> result; stack<TreeNode*> nodes; if(root != nullptr) nodes.push(root); while(nodes.size()>0) { TreeNode *tmp = nodes.top(); if(tmp != NULL) { nodes.pop(); if(tmp->right != nullptr) nodes.push(tmp->right); nodes.push(tmp); nodes.push(NULL); if(tmp->left != nullptr) nodes.push(tmp->left); } else { nodes.pop(); tmp = nodes.top(); result.push_back(tmp->val); nodes.pop(); } } return result; } };