LeetCode-94. Binary Tree Inorder Traversal

Description

Given a binary tree, return the inorder traversal of its nodes' values.

Example:

Input: [1,null,2,3]
   1
    \
     2
    /
   3

Output: [1,3,2]

Follow up

Recursive solution is trivial, could you do it iteratively?

Solution 1(C++)

class Solution {
public:
    vector<int> vectorAdd(vector<int> A, vector<int> B) {
        if(!A.size()) return B;
        if(!B.size()) return A;
        int a=A.size(), b=B.size();
        vector<int> res(a+b, 0);
        for(int i=0; i<a+b; i++){
            if(i<a) res[i]=A[i];
            else res[i]=B[i-a];
        }
        return res;
    }

    vector<int> inorderTraversal(TreeNode* root) {
        if(!root) return {};
        vector<int> res(1, root->val);
        vector<int> left = inorderTraversal(root->left);
        res = vectorAdd(left, res);
        vector<int> right = inorderTraversal(root->right);
        res = vectorAdd(res, right);
        return res;
    }
};

Solution 2(C++)

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> node_sofar;
        while(root || !node_sofar.empty()){
            if(root){
                node_sofar.push(root);
                root=root->left;
            }
            else{
                root=node_sofar.top();
                node_sofar.pop();
                res.push_back(root->val);
                root=root->right;
            }
        }
        return res;
    }
};

Solution 3(C++)

class Solution {
public:
    void inorder(TreeNode* root, vector<int>& nodes) {
        if (!root) return;
        inorder(root -> left, nodes);
        nodes.push_back(root -> val);
        inorder(root -> right, nodes);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> nodes;
        inorder(root, nodes);
        return nodes;
    } 
};

Solution 4(C++)

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        TreeNode* curNode = root;
        vector<int> nodes;
        while (curNode) {
            if (curNode -> left) {
                TreeNode* predecessor = curNode -> left;
                while (predecessor -> right && predecessor -> right != curNode)
                    predecessor = predecessor -> right;
                if (!(predecessor -> right)) {
                    predecessor -> right = curNode;
                    curNode = curNode -> left;
                }
                else {
                    predecessor -> right = NULL;
                    nodes.push_back(curNode -> val);
                    curNode = curNode -> right;
                }
            }
            else {
                nodes.push_back(curNode -> val);
                curNode = curNode -> right;
            }
        }
        return nodes;
    }
};

后续更新

二叉树的前序遍历参考如下:

算法分析

这是一道很经典的题目,二叉树的中序遍历。当然还有前序遍历与后序遍历。目前后面两题还没做,做了会在后面进行更新。

一共总结了四种方法:两种递归,一种迭代,一种Morris traversal。下面分别来说明一下。

1.递归:
递归对于三种顺序遍历都比较简单,按照定义来就好了,注意一下前序、中序、后序的英文:preorder、inorder、postorder。递归是解法一与解法三。解法一是自己写的,只能解决问题,算不上好方法。多多注意解法三。对于递归,一定要第一时间就能写出来。

2.递归:
递归对于前序遍历与中序遍历比较相似,都要利用栈,但是对于后序遍历比较麻烦。这里单说中序遍历。使用递归的思路与递归不一样。递归只用思考先对左子树调用递归函数,然后将自己放入vector,最后对右子树调用递归函数即可。要考虑递归,就要对实际树是如何进行中序遍历的全过程非常了解。然后从全过程中抽象出递归过程。中序遍历全过程是:先顺着左节点找到最深的左叶子节点,然后遍历该叶子结点的根节点,然后遍历另一个右叶子结点。这一层遍历完后,根节点变为上一层根节点。如果往上到最初根节点后,从右边继续之前的操作(最左->根->右->根的跟)。

如此,我们需要一个容器储存遍历过的所有根节点,考虑到全过程中对于根节点,最后储存的最先用到,是先进后出的特点,所以我们用栈stack。那么遍历过程可以用一个循环来表达:

  1. 当前节点是根节点,而后关注根节点的左子树,而后再关注左子树根节点的左子树……直到最终的某一个节点左子树不存在,不难发现,我们是一直沿着左子树下行的。
  2. 而后我们将进行回溯,找到最后一个遍历的,遍历该根节点,再关注该根节点的右子树存在的节点。
  3. 接下来对步骤2中所找到的节点进行步骤1的操作。

3.Morris traversal:
这种方法能实现常数空间,我在这里先不详细说明,主要目标是递归与迭代的熟练掌握。

程序分析

猜你喜欢

转载自blog.csdn.net/zy2317878/article/details/80559666
今日推荐