Leetcode 145. Binary Tree Postorder Traversal

来源:互联网 发布:2016年的网络流行词 编辑:程序博客网 时间:2024/04/28 04:10

题目描述:

Given a binary tree, return the postorder traversal of its nodes’ values.
For example:
Given binary tree {1,#,2,3},
1
\
2
/
3
return [3,2,1].
Note: Recursive solution is trivial, could you do it iteratively?

解题思路:
题目要求我们实现用迭代的方式后序遍历二叉树,这时候就需要使用到栈的数据结构, 我们基本的思想就是让他不断的向左走, 直到走到树的最左端, 然后回溯。 但是问题来了, 在回溯的过程中, 我如何才能判断我的右子树是否已经被遍历过了呢, ie,我应该在什么时候访问这个节点最合适?
想到这里, 我们想到图的遍历过程中, 有一个表记录着被访问过的节点的信息, 那么, 同样的我们也可以参考这样的思想, 用一个set结构记录节点的访问信息, 至此算法就出来了

下面是我们的代码部分:

/** * Definition for binary tree * struct TreeNode { *     int val; *     TreeNode *left; *     TreeNode *right; *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solution {public:    vector<int> postorderTraversal(TreeNode* root) {        stack<TreeNode *> mystack;        set<TreeNode *> isvisited;        vector<int> res;        while (!mystack.empty() || root){            // 如果节点非空, 压栈            if (root){                mystack.push(root);                root = root->left;            }            else{                // 只有当左子树遍历完了, 才到这里                TreeNode * top = mystack.top();                if (top->right == nullptr || isVisited(isvisited, top->right)){                    // 右子树为空或者右子树已经被遍历过了, 更新访问表, 并输出                    res.push_back(top->val);                    isvisited.insert(top);                    mystack.pop();                }                else{                    // 右子树没有被遍历过, 需要对右子树遍历                    root = top->right;                }            }        }        return res;    }private:    inline bool isVisited(set<TreeNode *> & myset, TreeNode * data){        return (myset.find(data) == myset.end()) ? false : true;    }};

然后我们查看了一下, 我们3个月前提交的代码, 发现思路是一样的, 不过当时是采用定义一个新的数据结构来记录左右子树的访问与否。

struct stackNode{        TreeNode * node;        bool right;        bool left;        stackNode(TreeNode * x, bool bleft, bool bright) : node(x), left(bleft), right(bright){}    };

相当于将原来的数据结构又做了一层封装。
代码如下:

//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 {private:    struct stackNode{        TreeNode * node;        bool right;        bool left;        stackNode(TreeNode * x, bool bleft, bool bright) : node(x), left(bleft), right(bright){}    };public:    vector<int> postorderTraversal(TreeNode* root) {        if (root == nullptr)            return vector<int>();        vector<int> res;        stack<stackNode> mystack;        while (root || !mystack.empty()){            if (root){                mystack.emplace(stackNode(root, true, false));                root = root->left;            }            else{                stackNode tmp = mystack.top();                root = tmp.node;                mystack.pop();                if (tmp.right == false){                    mystack.emplace(stackNode(tmp.node, true, true));                    root = root->right;                }                else{                    res.push_back(tmp.node->val);                    root = nullptr;                }            }        }        return res;    }};

网上有大神的解法, 不需要使用访问表, 基本思想:
记录上次回溯的节点, 此时由于需要回溯, root == nullptr, 然后判断这个节点是否是当前栈顶节点的右节点, 就可以判断出当前节点的右子树是否已经被遍历过了。 特别巧妙的一种方法!!

vector<int> postorderTraversal(TreeNode* root) {    vector<int> nodes;    stack<TreeNode*> toVisit;    TreeNode* curNode = root;    TreeNode* lastNode = NULL;    while (curNode || !toVisit.empty()) {        if (curNode) {            toVisit.push(curNode);            curNode = curNode -> left;        }        else {            TreeNode* topNode = toVisit.top();            if (topNode -> right && lastNode != topNode -> right)                curNode = topNode -> right;            else {                nodes.push_back(topNode -> val);                lastNode = topNode;                toVisit.pop();            }        }    }    return nodes;}

当然还有一种思路是使用 Morris 翻转, 这个算法没有仔细研究, 大家可以百度一下。

参考资料:
0 ms Clear C++ solutions — iterative, recursive, Morris traversal (3 different solutions!)

0 0
原创粉丝点击