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.递归算法的递归定义是:

若二叉树为空,则遍历结束;否则
⑴ 后序遍历左子树(递归调用本算法);
⑵ 后序遍历右子树(递归调用本算法) ;
⑶ 访问根结点 。

对有n个结点的二叉树,其时间复杂度均为O(n) 。

 List<Integer> postOrder = new ArrayList<Integer>();
public List<Integer> postorderRecursion(TreeNode root) {
if ((root != null) && (root.val != '#')) {
postorderRecursion(root.left);
postorderRecursion(root.right);
postOrder.add(root.val);
}
return postOrder;
}

2.非递归算法

在后序遍历中,根结点是最后被访问的。因此,在遍历过程中,当搜索指针指向某一根结点时,不能立即访问,而要先遍历其左子树,此时根结点进栈。当其左子树遍历完后再搜索到该根结点时,还是不能访问,还需遍历其右子树。所以,此根结点还需再次进栈,当其右子树遍历完后再退栈到到该根结点时,才能被访问。

因此,设立一个状态标志变量tag :{ 0 : 结点暂不能访问;1 : 结点可以被访问}。

其次,设两个堆栈S1、S2 ,S1保存结点,S2保存结点的状态标志变量tag 。S1和S2共用一个栈顶指针。

设T是指向根结点的指针变量,非递归算法是:

若二叉树为空,则返回;否则,令p=T;

⑴ 第一次经过根结点p,不访问:

p进栈S1 , tag 赋值0,进栈S2,p=p->Lchild 。

⑵ 若p不为空,转(1),否则,取状态标志值tag :

⑶ 若tag=0:对栈S1,不访问,不出栈;修改S2栈顶元素值(tag赋值1) ,取S1栈顶元素的右子树,即p=S1[top]->Rchild ,转(1);

⑷ 若tag=1:S1退栈,访问该结点;

直到栈空为止。

 List<Integer> postOrder = new ArrayList<Integer>();
public List<Integer> postorderTraversal(TreeNode p) {
Stack<TreeNode> stack = new Stack<TreeNode>();
Stack<Boolean> tag = new Stack<Boolean>();
while ((p != null) || !stack.isEmpty()) {
if (p != null) {
stack.push(p);
tag.push(false);
p = p.left;
} else {
boolean visit = tag.pop();
if (visit) {
postOrder.add(stack.pop().val);
} else {
tag.push(true);
p = stack.peek().right;
}
}
}
return postOrder;
}

二叉树的三种遍历递归和非递归实现:递归实现都简单;非递归的前序和中序实现简单,后序采用2个栈来实现(参考严蔚敏的思路,比较容易理解)。代码如下:

 import java.util.ArrayList;
import java.util.List;
import java.util.Stack; import javax.swing.text.AbstractDocument.LeafElement; /**
* Definition for binary tree public class TreeNode { int val; TreeNode left;
* TreeNode right; TreeNode(int x) { val = x; } }
*/
public class TreeNodeSolution { public List<Integer> preorderRecursion(TreeNode root) {
List<Integer> preOrder = new ArrayList<Integer>();
if ((root != null) && (root.val != '#')) {
preOrder.add(root.val);
postorderRecursion(root.left);
postorderRecursion(root.right);
}
return preOrder;
} public List<Integer> inorderRecursion(TreeNode root) {
List<Integer> inOrder = new ArrayList<Integer>();
if ((root != null) && (root.val != '#')) {
postorderRecursion(root.left);
inOrder.add(root.val);
postorderRecursion(root.right);
}
return inOrder;
} public List<Integer> postorderRecursion(TreeNode root) {
List<Integer> postOrder = new ArrayList<Integer>();
if ((root != null) && (root.val != '#')) {
postorderRecursion(root.left);
postorderRecursion(root.right);
postOrder.add(root.val);
}
return postOrder;
} public List<Integer> inorderTraversal(TreeNode p) {
List<Integer> inOrder = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
while ((p != null) || !stack.isEmpty()) {
if (p != null) {
stack.push(p);
p = p.left;
} else {
p = stack.pop();
inOrder.add(p.val);
p = p.right;
}
}
return inOrder;
} public List<Integer> preorderTraversal(TreeNode p) {
List<Integer> preOrder = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
while ((p != null) || !stack.isEmpty()) {
if (p != null) {
preOrder.add(p.val);
stack.push(p);
p = p.left;
} else {
p = stack.pop();
p = p.right;
}
}
return preOrder;
} public List<Integer> postorderTraversal(TreeNode p) {
List<Integer> postOrder = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
Stack<Boolean> tag = new Stack<Boolean>();
while ((p != null) || !stack.isEmpty()) {
if (p != null) {
stack.push(p);
tag.push(false);
p = p.left;
} else {
boolean visit = tag.pop();
if (visit) {
postOrder.add(stack.pop().val);
} else {
tag.push(true);
p = stack.peek().right;
}
}
}
return postOrder;
} public static void main(String[] args) {
TreeNode t1 = new TreeNode(1);
TreeNode t2 = new TreeNode(2);
TreeNode t3 = new TreeNode(3);
t1.setRight(t2);
t1.setLeft(t3);
System.out.println(new TreeNodeSolution().postorderTraversal(t1));
}
}

LeetCode解题报告:Binary Tree Postorder Traversal的更多相关文章

  1. 【LeetCode】145. Binary Tree Postorder Traversal (3 solutions)

    Binary Tree Postorder Traversal Given a binary tree, return the postorder traversal of its nodes' va ...

  2. 【LEETCODE OJ】Binary Tree Postorder Traversal

    Problem Link: http://oj.leetcode.com/problems/binary-tree-postorder-traversal/ The post-order-traver ...

  3. 【LeetCode】145. Binary Tree Postorder Traversal 解题报告 (C++&Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 迭代 日期 题目地址:https://leetc ...

  4. LeetCode OJ 145. Binary Tree Postorder Traversal

    Given a binary tree, return the postorder traversal of its nodes' values. For example:Given binary t ...

  5. LeetCode OJ:Binary Tree Postorder Traversal(后序遍历二叉树)

    Given a binary tree, return the postorder traversal of its nodes' values. For example:Given binary t ...

  6. 【LeetCode】145. Binary Tree Postorder Traversal

    Difficulty: Hard  More:[目录]LeetCode Java实现 Description https://leetcode.com/problems/binary-tree-pos ...

  7. LeetCode题解之Binary Tree Postorder Traversal

    1.题目描述 2.问题分析 递归 3.代码 vector<int> postorderTraversal(TreeNode* root) { vector<int> v; po ...

  8. LeetCode: Binary Tree Postorder Traversal 解题报告

    Binary Tree Postorder Traversal Given a binary tree, return the postorder traversal of its nodes' va ...

  9. C++版 - LeetCode 145: Binary Tree Postorder Traversal(二叉树的后序遍历,迭代法)

    145. Binary Tree Postorder Traversal Total Submissions: 271797 Difficulty: Hard 提交网址: https://leetco ...

随机推荐

  1. JDK8新特性之接口

    在JDK7及以前的版本中,接口中都是抽象方法,不能定义方法体,但是从jdk8开始,接口中可以定义静态的非抽象的方法,直接使用接口名调用静态方法,但是它的实现类的类名或者实例却不可以调用接口中的静态方法 ...

  2. Linux bash中的变量分类

    1.本地变量 VAR=XYZ 2.局部变量 local VAR=XYZ 3.环境变量 在子shell中可以起作用 export VAR=XYZ 4.位置变量 $0 脚本名本身 $1 第一个参数 $2 ...

  3. 图像本地预览插件(基于JQUERY、HTML5)

    最近是被这项目搞疯了.害我天天写插件,上周才写,现在就继续吧..... 说说这个吧.主要是用于本地图像预览的.我们知道在以前,图像预览一般都很麻烦,一般都是异步上传然后返回路径,动态设置路径,但是这样 ...

  4. asp.net各种获取客户端ip方法

    Request.ServerVariables("REMOTE_ADDR") 来取得客户端的IP地址,但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的IP地址,而不是真 ...

  5. [访问系统] Api_Win32_Mac类工具包 (转载)

    点击下载 Api_Win32_Mac.zip using System; using System.Collections.Generic; using System.Linq; using Syst ...

  6. C#编程使用到的几种调试方式

    一.前言: 使用C#语言从08年算起,到现在也有6个年头的时间了. 但 是会使用调试进行辅助编程的时间,却只有5个年头,其中第一年里面,只能傻傻地敲着老师给的案例,不会写就一遍一遍重复手写编码,上机练 ...

  7. html》meta标签笔记

    meta是html语言head区的一个辅助性标签.也许你认为这些代码可有可无.其实如果你能够用好meta标签,会给你带来意想不到的效果,meta标签的作用有:搜索引擎优化(SEO),定义页面使用语言, ...

  8. 关于 const 成员函数

    成员函数如果是const意味着什么? 有两个流行概念:物理常量性和逻辑常量性. C++对常量性的定义采用的是物理常量性概念,即const 成员函数不可以更改对象内任何non-static成员变量.例如 ...

  9. VS 2012中消失了的Create UnitTest

    前言:最近正在研究一个新项目的开发工作,这个项目的要求是必须写UnitTest,对于我个人来讲是很不喜欢写UnitTest的感觉这个东西会很大程度的延误开发进度,所以之前项目的UnitTest是能不写 ...

  10. jquery 只有二级下拉菜单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...