【LeetCode】145. Binary Tree Postorder Traversal 解题报告



转载请注明出处:http://blog.csdn.net/crazy1235/article/details/51494797


Subject

出处:https://leetcode.com/problems/binary-tree-postorder-traversal/

Hard 级别

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].

Explain

求二叉树的后续遍历。


Solution

solution 1

递归方式

    private List<Integer> resultList = new ArrayList<Integer>();

    /**
     * 递归方式 <br />
     * 1ms
     *
     * @param root
     * @return
     */
    public List<Integer> postorderTraversal(TreeNode root) {
        postOrder(root);
        return resultList;
    }

    private void postOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        if (node.left != null) {
            postOrder(node.left);
        }
        if (node.right != null) {
            postOrder(node.right);
        }
        resultList.add(node.val);
    }

LeetCode上Run Time 是 1ms

Your runtime beats 70.01% of java submissions.


solution 2

非递归方式的思想就是需要记录访问的结点是否是第一次访问的。因为当前结点需要在左右子数访问之后才能输出

所以需要标志来记录当前结点是否是第一次访问。当第二次访问的时候才输出。

    /**
     * 后续遍历非递归方法
     * 根据中序非递归方式改造而来
     * @author jacksen
     * @param node
     */
    public List<Integer> postorderTraversal1(TreeNode node) {
        if (node == null) {
            return resultList;
        }
        Stack<WrapperNode> stack = new Stack<>();
        WrapperNode wrapperNode = new WrapperNode(node, false);
        stack.push(wrapperNode);
        while (!stack.isEmpty()) {
            while ((wrapperNode = stack.peek()).node != null) {
                wrapperNode = new WrapperNode(wrapperNode.node.left, false);
                stack.push(wrapperNode);
            }
            //
            stack.pop();
            //
            wrapperNode = stack.peek();
            while (wrapperNode.node != null) {
                if (wrapperNode.isFinished) {
                    resultList.add(stack.pop().node.val);
                    if (stack.isEmpty()) {
                        return resultList;
                    }
                    wrapperNode = stack.peek();
                } else {
                    wrapperNode.isFinished = true;
                    wrapperNode = new WrapperNode(wrapperNode.node.right, false);
                    stack.push(wrapperNode);
                    break;
                }
            }
        }
        return resultList;
    }
    /**
     * TreeNode包装类
     *
     * @author jacksen
     */
    private static class WrapperNode {
        TreeNode node;
        boolean isFinished;

        public WrapperNode(TreeNode node, boolean isFinished) {
            this.node = node;
            this.isFinished = isFinished;
        }
    }

先从根节点往左,把最左侧的一条分支入栈。

最左侧走到叶子结点之后,去添加它的右子数。并将当前结点访问标志改变。

判断访问标志来pop结点


solution 3

solution 2的非递归方式,是先访问左子树。

其实可以从根结点,然后访问右子树。

参照 : http://www.cnblogs.com/Antech/p/3655594.html

    /**
     * 非递归方式 <br />
     * 3ms <br />
     * http://www.cnblogs.com/Antech/p/3655594.html
     *
     * @param root
     * @return
     */
    private List<Integer> postorderTraversal2(TreeNode root) {
        if (root == null) {
            return resultList;
        }
        Stack<WrapperNode> stack = new Stack<>();
        stack.push(new WrapperNode(root, false));
        WrapperNode wrapperNode = null;
        while (!stack.isEmpty()) {
            wrapperNode = stack.peek();
            if (wrapperNode.node == null) {
                stack.pop();
                continue;
            }
            if (wrapperNode.isFinished) {
                resultList.add(stack.pop().node.val);
            } else {
                stack.push(new WrapperNode(wrapperNode.node.right, false));
                stack.push(new WrapperNode(wrapperNode.node.left, false));
                wrapperNode.isFinished = true;
            }
        }
        return resultList;
    }

solution 4

在solution 3的基础上进行改进。

判断左右子节点是否为null,进而少一次while判断,也少入栈出栈操作。

    /**
     * 方法二非递归方式的改进 <br />
     * 3ms <br />
     *
     * @param root
     * @return
     */
    private List<Integer> postorderTraversal3(TreeNode root) {
        if (root == null) {
            return resultList;
        }
        Stack<WrapperNode> stack = new Stack<>();
        stack.push(new WrapperNode(root, false));
        WrapperNode wrapperNode = null;
        while (!stack.isEmpty()) {
            wrapperNode = stack.peek();
            if (wrapperNode.isFinished) {
                resultList.add(stack.pop().node.val);
            } else {
                wrapperNode.isFinished = true;
                if (wrapperNode.node.right != null) {
                    stack.push(new WrapperNode(wrapperNode.node.right, false));
                }
                if (wrapperNode.node.left != null) {
                    stack.push(new WrapperNode(wrapperNode.node.left, false));
                }
            }
        }
        return resultList;
    }

solution 5

接下来介绍一个牛逼的方法。

该方法使用两个栈进行处理,代码看上去简单易懂。

    /**
     * 使用两个栈 <br />
     * 2ms <br />
     *
     * https://leetcode.com/discuss/102843/my-ac-java-solution-using-two-stacks
     *
     * @param root
     * @return
     */
    private List<Integer> postorderTraversal4(TreeNode root) {
        if (root == null) {
            return resultList;
        }
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<TreeNode> stack2 = new Stack<>();

        stack1.push(root);

        TreeNode tempNode = null;

        while (!stack1.isEmpty()) {
            tempNode = stack1.pop();
            if (tempNode.left != null) {
                stack1.push(tempNode.left);
            }
            if (tempNode.right != null) {
                stack1.push(tempNode.right);
            }
            stack2.push(tempNode);
        }

        while (!stack2.isEmpty()) {
            resultList.add(stack2.pop().val);
        }

        return resultList;
    }

对该方法仔细研究,就会发现stack2里面存储的就是后续遍历输出的整个顺序。

后序遍历就是【左右根】的形式输出。

所以stack1中先入根然后pop出来,然后入左和右。这样stack1先pop根,然后pop右,接着pop左;

正好,stack2先入根,然后入右,接着入左。

故,stack2 循环pop的时候就是【左右根】的顺序。


solution 6

其实,仔细想想,先序输出的时候是【根左右】,后序输出是【左右根】,

所以只需要按照先序遍历非递归的方法,输出的时候改改顺序即可。

    /**
     * https://leetcode.com/discuss/71943/preorder-inorder-and-postorder-
     * iteratively-summarization <br />
     *
     * LinkedList
     *
     * @param root
     * @return
     */
    public List<Integer> postorderTraversal5(TreeNode root) {
        LinkedList<Integer> list = new LinkedList<>();
        if (root == null) {
            return list;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode tempNode = root;
        while (!stack.isEmpty() || tempNode != null) {
            if (tempNode != null) {
                stack.push(tempNode);
                list.addFirst(tempNode.val);
                tempNode = tempNode.right;
            } else {
                tempNode = stack.pop().left;
            }
        }

        return list;
    }

该方法使用LinkedList

每次都调用addFirst()方法,将结点添加到头部

所以顺序就是【左】【右】【根】


solution 7

根据solution 6的思想和solution 7的方式,可以将先序遍历非递归方式简单修改一下即可。

Binary Tree Inorder Traversal 非递归方法

    /**
     * 非递归方式 <br />
     *
     * 参考 Pre order 的preorderTraversal2
     *
     * @author jacksen
     *
     * @param root
     * @return
     */
    public List<Integer> postorderTraversal6(TreeNode root) {
        LinkedList<Integer> list = new LinkedList<>();
        if (root == null) {
            return list;
        }
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        TreeNode tempNode = null;
        while (!stack.isEmpty()) {
            tempNode = stack.pop();
            list.addFirst(tempNode.val);
            if (tempNode.left != null) {
                stack.push(tempNode.left);
            }
            if (tempNode.right != null) {
                stack.push(tempNode.right);
            }
        }
        return list;
    }

该方法使用一个栈加上一个单链表。



OK! 介绍完毕~

欢迎留言,批评指正~~~

时间: 2024-08-05 07:08:25

【LeetCode】145. Binary Tree Postorder Traversal 解题报告的相关文章

LeetCode: Binary Tree Postorder Traversal 解题报告

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

LeetCode 145 Binary Tree Postorder Traversal(二叉树的后续遍历)+(二叉树、迭代)

翻译 给定一个二叉树,返回其后续遍历的节点的值. 例如: 给定二叉树为 {1, #, 2, 3} 1 2 / 3 返回 [3, 2, 1] 备注:用递归是微不足道的,你可以用迭代来完成它吗? 原文 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: Recur

LeetCode 145 Binary Tree Postorder Traversal(二叉树的兴许遍历)+(二叉树、迭代)

翻译 给定一个二叉树.返回其兴许遍历的节点的值. 比如: 给定二叉树为 {1. #, 2, 3} 1 2 / 3 返回 [3, 2, 1] 备注:用递归是微不足道的,你能够用迭代来完毕它吗? 原文 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: Recur

LeetCode 144. Binary Tree Preorder Traversal 解题报告

144. Binary Tree Preorder Traversal My Submissions Question Total Accepted: 108336 Total Submissions: 278322 Difficulty: Medium Given a binary tree, return the preorder traversal of its nodes' values. For example: Given binary tree {1,#,2,3}, 1 2 / 3

Java for LeetCode 145 Binary Tree Postorder Traversal

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]. 后序遍历,左子树→右子树→根节点 前序遍历的非递归实现需要一个计数器,方法是需要重写一个类继承TreeNode,翁慧玉教材<数据结构:题解与拓展>P113有详细介绍,这里略.递归JAVA实现如下: public Lis

Leetcode #145 Binary Tree Postorder Traversal

题目链接:https://leetcode.com/problems/binary-tree-postorder-traversal/ (非递归实现)二叉树的后序遍历. 1 class Solution 2 { 3 public: 4 vector<int> postorderTraversal(TreeNode *root) 5 { 6 vector<int> output; 7 if(root == NULL) 8 { 9 return output; 10 } 11 12 s

【Leetcode】Binary Tree Postorder Traversal

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? 思路:后序遍历比起先序遍历以及中序遍历要稍微复杂一点,可以考虑用两个stack进行操作,

leetcode题解:Binary Tree Postorder Traversal (二叉树的后序遍历)

题目: 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? 说明: 1) 两种实现,递归与非递归 , 其中非递归有两种方法 2)复杂度分析:时

[LeetCode][JavaScript]Binary Tree Postorder Traversal

Binary Tree Postorder Traversal 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? 同样的配方,同样的味道.