【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 resultList = new ArrayList();

    /**
     * 递归方式 
* 1ms * * @param root * @return */
public List 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

    /**
     * 非递归方式 
* 3ms
* http://www.cnblogs.com/Antech/p/3655594.html * * @param root * @return */
private List postorderTraversal2(TreeNode root) { if (root == null) { return resultList; } Stack 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判断,也少入栈出栈操作。

    /**
     * 方法二非递归方式的改进 
* 3ms
* * @param root * @return */
private List postorderTraversal3(TreeNode root) { if (root == null) { return resultList; } Stack 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

接下来介绍一个牛逼的方法。
该方法使用两个栈进行处理,代码看上去简单易懂。

    /**
     * 使用两个栈 
* 2ms
* * https://leetcode.com/discuss/102843/my-ac-java-solution-using-two-stacks * * @param root * @return */
private List postorderTraversal4(TreeNode root) { if (root == null) { return resultList; } Stack stack1 = new Stack<>(); Stack 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 
* * LinkedList * * @param root * @return */
public List postorderTraversal5(TreeNode root) { LinkedList list = new LinkedList<>(); if (root == null) { return list; } Stack 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 非递归方法

    /**
     * 非递归方式 
* * 参考 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! 介绍完毕~

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

你可能感兴趣的:(Java开发,算法学习,LeetCode解题报告,Java,篇)