题目链接

题目大意:后序遍历二叉树。

法一:普通递归,只是这里需要传入一个list来存储遍历结果。代码如下(耗时1ms):

     public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
list = dfs(root, list);
return list;
}
public static List<Integer> dfs(TreeNode root, List<Integer> list) {
if(root == null) {
return list;
}
else {
list = dfs(root.left, list);
list = dfs(root.right, list);
list.add(root.val);
return list;
}
}

法二(借鉴):后序遍历顺序是“左右根”,这里将其反过来遍历,也就是“根右左”,然后将遍历结果反转返回即可。这里用到了LinkedList.addFirst()方法,即将值插到链表头部。(addLast()方法与add()方法一样是插到链表尾部)。这里也可以用ArrayList.add(),在最后再调用Collections.reverse(list)方法即可。此方法代码简单,但不是很好想。代码如下(耗时1ms):

     public List<Integer> postorderTraversal(TreeNode root) {
LinkedList<Integer> list = new LinkedList<Integer>();
if(root == null) {
return list;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
TreeNode tmp = null;
while(!stack.isEmpty()) {
tmp = stack.pop();
list.addFirst(tmp.val);
if(tmp.left != null) {
stack.push(tmp.left);
}
if(tmp.right != null) {
stack.push(tmp.right);
}
}
return list;
}

法三(借鉴):普通后序非递归遍历,这里用一个辅助栈来标记结点是否已经访问右结点,如果已经访问右结点,则将根值加入list中,否则访问右结点压栈。因为有两个栈要压栈出栈,耗时较长。也可以在TreeNode结点中加入一个标记属性flag来标记是否访问过右结点,这样就不需要辅助栈了,时间应该会快一些。代码如下(耗时2ms):

     public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
if(root == null) {
return list;
}
Stack<TreeNode> stackNode = new Stack<TreeNode>();
//0表示右结点未访问,1表示右结点已访问
Stack<Integer> stackFlag = new Stack<Integer>();
stackNode.push(root);
stackFlag.push(0);
TreeNode tmp = root.left;//已压栈,则访问其左结点
while(!stackNode.isEmpty()) {
while(tmp != null) {
stackNode.push(tmp);
stackFlag.push(0);
tmp = tmp.left;
}
if(stackFlag.peek() == 0) {
//右结点未访问,则访问右结点
tmp = stackNode.peek().right;
stackFlag.pop();
stackFlag.push(1);//将访问右结点状态置1
}
else {
//右结点已访问,则将根结点加入list队列,并将根节点弹出
list.add(stackNode.pop().val);
stackFlag.pop();//弹出根节点状态值
}
}
return list;
}

法四(借鉴):保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存 在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了 每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。这个比法二还要难理解,特别是要先压right再压left。代码如下(耗时2ms):

     public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
if(root == null) {
return list;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
TreeNode pre = null, cur = null;
while(!stack.isEmpty()) {
cur = stack.peek();//判断当前结点情况,所以用peek不用pop
if((cur.left == null && cur.right == null) ||
(pre != null && (pre == cur.left || pre == cur.right))) {
//如果当前结点没有左右孩子则直接弹出当前结点
//如果当前结点的左右孩子都已经访问完则弹出当前结点
list.add(cur.val);
pre = cur;
stack.pop();
}
else {
//注意这里一定要先压right再压left,因为栈的先进后出的原则,到时候会先弹出left再弹出right,这样的顺序才正确。
if(cur.right != null) {
stack.push(cur.right);
}
if(cur.left != null) {
stack.push(cur.left);
}
}
}
return list;
}

法五(借鉴):最接近先序、中序非递归遍历的方法,先压左结点再判断栈顶元素。代码如下(耗时2ms):

 public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
if(root == null) {
return list;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
TreeNode pre = null, cur = root.left;
while(!stack.isEmpty()) {
while(cur != null) {
stack.push(cur);
cur = cur.left;
}
//判断栈顶结点
cur = stack.peek();
//判断是否访问栈顶结点
if(cur.right != null && pre != cur.right) {
//如果不是从右孩子返回,即还未访问右孩子,则访问
cur = cur.right;
}
else {
//如果没有右孩子或右孩子已经访问过,则直接弹出当前节点进行访问
list.add(cur.val);
stack.pop();
//记录当前访问的结点
pre = cur;
//将当前结点赋空
cur = null;
}
}
return list;
}

145.Binary Tree Postorder Traversal---二叉树后序非递归遍历的更多相关文章

  1. [Leetcode] Binary tree postorder traversal二叉树后序遍历

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

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

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

  3. LeetCode:145_Binary Tree Postorder Traversal | 二叉树后序遍历 | Hard

    题目:Binary Tree Postorder Traversal 二叉树的后序遍历,题目要求是采用非递归的方式,这个在上数据结构的课时已经很清楚了,二叉树的非递归遍历不管采用何种方式,都需要用到栈 ...

  4. [LeetCode] 145. Binary Tree Postorder Traversal 二叉树的后序遍历

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

  5. LeetCode 145. Binary Tree Postorder Traversal二叉树的后序遍历 (C++)

    题目: Given a binary tree, return the postorder traversal of its nodes' values. Example: Input: [1,nul ...

  6. LeetCode 145. Binary Tree Postorder Traversal 二叉树的后序遍历 C++

    Given a binary tree, return the postorder traversal of its nodes' values. Example: Input: [,,] \ / O ...

  7. 145 Binary Tree Postorder Traversal 二叉树的后序遍历

    给定一棵二叉树,返回其节点值的后序遍历.例如:给定二叉树 [1,null,2,3],   1    \     2    /   3返回 [3,2,1].注意: 递归方法很简单,你可以使用迭代方法来解 ...

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

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

  9. 94.Binary Tree Inorder Traversal---二叉树中序非递归遍历

    题目链接 题目大意:中序遍历二叉树.先序见144,后序见145. 法一:DFS,没啥说的,就是模板DFS.代码如下(耗时1ms): public List<Integer> inorder ...

随机推荐

  1. 常州day3

    Task1 小 W 得到了一堆石子,要放在 N 条水平线与 M 条竖直线构成的网格的交点上.因为小 M 最喜欢矩形了, 小 W 希望知道用 K 个石子最多能找到多少四边平行于坐标轴的长方形,它的四个角 ...

  2. 洛谷p1017 进制转换(2000noip提高组)

    洛谷P1017 进制转换 题意分析 给出一个数n,要求用负R进制显示. n∈[-32768,32767].R ∈[-20,-2] 考察的是负进制数的转换,需要理解短除法. 看到这道题的时候,我是比较蒙 ...

  3. 函数式编程(1)-高阶变成(3)-sorted

    sorted 排序算法 排序也是在程序中经常用到的算法.无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小.如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大 ...

  4. SpringBoot web 小项目

    Spring Boot 整合 Thymeleaf 完整 Web 案例 原创出处  作者:泥瓦匠BYSocket 希望转载,保留摘要,谢谢! Thymeleaf 是一种模板语言.那模板语言或模板引擎是什 ...

  5. AtCoder Regular Contest 088 E - Papple Sort(树状数组+结论)

    结论:每次把字符丢到最外面最优,用树状数组统计答案,把字符放到最外边后可以当成消失了,直接在树状数组上删掉就好. 感性理解是把字符丢到中间会增加其他字符的移动次数,但是丢到外面不会,所以是正确的. # ...

  6. 解题:由乃OI 2018 五彩斑斓的世界

    题面 写在前面的扯淡: 分块的总体学习告一段落,这算是分块集中学习的最后一题么:以后当然也可能会写,就是零零散散的题了=.= 在洛谷上搜ynoi发现好像只有这道题和 由乃OI 2018 未来日记 是分 ...

  7. 【bzoj4571】美味

    Portal -->bzoj4571 Solution emmm持续智力康复.. 虽然说因为统计的是加上\(x\)的跟\(b\)异或的最大值所以可持久化trie用不了了 ​ 但是按位贪心的思想还 ...

  8. Linux基础-----------nginx安装和nginx web、nginx反向代理、nfs 服务

    作业一:nginx服务1)二进制安装nginx包 yum install epel-release -y 先安装epel-release 再查看yum源中已经安装上了epel相关文件 中间省去了一些安 ...

  9. 【分块】【P2801】教主的魔法

    Description 给你一个长度为 \(n\) 的序列,要求资瓷区间加,查询区间大于等于 \(k\) 的数的个数 Input 第一行是 \(n~,~Q\) 代表序列长度和操作个数 下面一行代表序列 ...

  10. js浏览器调试方法

    chrome浏览器可在需要断点的地方写一个关键字 "debugger",这样在 js 运行到这里的时候会停止继续运行,并可以查看当前状态