三种对应时间和空间复杂度
1. Iterative way (stack). Time: O(n), Space: O(n).
2. Recursive solution. Time: O(n), Space: O(n).
3. Threaded tree (Morris). Time: O(n), Space: O(1).
二叉树中序遍历
给定一个二叉树,返回它的中序 遍历。
示例:
输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
递归方式:
void inorder(vector<int>& res,TreeNode* root){
if(!root) return;
inorder(res,root->left);
res.push_back(root->val);
inorder(res,root->right);
}
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
if(!root) return{};
vector<int> res;
inorder(res,root);
return res;
}
};
使用栈的非递归方式:
循环停止条件:
当前结点不为空,或者栈不为空。
因为结点为空说明已经访问到了底;但是栈中所有结点正好对应树所有结点,所以没有空的话就表示还没有弄完。
先放入根节点,再放所有左结点。
只用考虑当前结点的右结点就可以。
因为当前结点可能存在一个右结点,然后右结点又存在左右结点,所以只用找到最底层左结点的右结点就可以了。
p=p->right;
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
if(!root) return{};
vector<int> res;
stack<TreeNode*> s;
TreeNode* p = root;
while(p || !s.empty()){
while(p){
s.push(p);
p=p->left;
}
p = s.top();
s.pop();
res.push_back(p->val);
p=p->right;
}
return res;
}
};
Morris Traversal(螺纹二叉树)
这种方法不需要使用栈,所以空间复杂度为常量,这种非递归不用栈的遍历方法有个专门的名字,叫Morris Traversal。
根据别人的blog写的:Morris Traversal
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
if(!root) return {};
vector<int> res;
TreeNode* pre,*cur;
cur = root;
while(cur){
//1.如果已经是最底层左结点,直接输出
if(!cur->left){
res.push_back(cur->val);
cur = cur->right;//新的二叉树有一条“路”,为了完成左->根->右访问,这条路保存了左子树上最右侧结点和根的路径
}
//2.先找寻,左子树中,最右侧结点
else{
pre = cur->left;
while(pre->right && pre->right !=cur/*完成新树之后,左子树最右侧结点和根联通了,不能让它返回到根部*/)
pre = pre->right;
//2.a 构建一条新的路径:左子树上最右侧结点到根
if(!pre->right){
pre->right = cur;
cur = cur->left;//寻找下一层左子树的最右侧...
}
//2.b 把这一条添加的路径销毁,到这一步实际上cur已经回到了根节点
else{
pre->right = NULL;
res.push_back(cur->val);
cur = cur->right;//此时应该去访问右子树了。
}
}
}
return res;
}
};