145. 二叉树的后序遍历

知识点:二叉树;递归;Morris遍历

题目描述

给定一个二叉树的根节点 root ,返回它的 后序 遍历。

示例

输入: [1,null,2,3]
1
\
2
/
3 输出: [3,2,1]

解法一:递归

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
List<Integer> list = new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if(root == null) return list;
postorderTraversal(root.left);
postorderTraversal(root.right);
list.add(root.val);
return list;
}
}

时间复杂度:0(N),每个节点恰好被遍历一次;

空间复杂度:O(N),递归过程中栈的开销;

解法二:迭代法

后序遍历可以用前序遍历来解决,想一下前序遍历:根左右,我们先压右树再压左树。怎么实现根右左呢,可以先压左树再压右树嘛,然后反过来不就是左右根了吗?(反过来用栈来实现,栈一个很大的作用就是实现逆序)

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
List<Integer> list = new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
Stack<TreeNode> stackA = new Stack<>();
Stack<TreeNode> stackB = new Stack<>();
if(root == null) return list;
stackA.push(root);
while(!stackA.isEmpty()){
TreeNode top = stackA.pop();
stackB.push(top);
if(top.left != null) stackA.push(top.left);
if(top.right != null) stackA.push(top.right);
}
while(!stackB.isEmpty()){
list.add(stackB.pop().val);
}
return list;
}
}

解法三:Morris遍历

构建从下到上的连接,一条路能够走遍所有节点;

当我们返回上层之后,也就是将连线断开的时候,打印下层的单链表。

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
List<Integer> list = new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if(root == null) return list;
TreeNode cur = root;
TreeNode mostRightNode = null;
while(cur != null){
mostRightNode = cur.left;
if(mostRightNode != null){
while(mostRightNode.right != null && mostRightNode.right != cur){
mostRightNode = mostRightNode.right;
}
if(mostRightNode.right == null){
mostRightNode.right = cur;
cur = cur.left;
continue;
}else{
mostRightNode.right = null;
postMorrisPrint(cur.left); //第二次到达时打印下一层的单链表;
cur = cur.right;
}
}else{
cur = cur.right;
}
}
postMorrisPrint(root);
return list;
}
private void postMorrisPrint(TreeNode node){
TreeNode reverseList = reverseList(node); //反转单链表;
TreeNode cur = reverseList;
while(cur != null){
list.add(cur.val);
cur = cur.right;
}
reverseList(reverseList);
}
private TreeNode reverseList(TreeNode node){
TreeNode pre = null;
TreeNode cur = node;
while(cur != null){
TreeNode next = cur.right;
cur.right = pre;
pre = cur;
cur = next;
}
return pre;
}
}

体会

后序遍历的特殊在于其Morris遍历;

相关链接

二叉树

【LeetCode】145. 二叉树的后序遍历的更多相关文章

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

    145. 二叉树的后序遍历 145. Binary Tree Postorder Traversal 题目描述 给定一个二叉树,返回它的 后序 遍历. LeetCode145. Binary Tree ...

  2. Java实现 LeetCode 145 二叉树的后序遍历

    145. 二叉树的后序遍历 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很简单,你可以通过迭代算法完成 ...

  3. LeetCode 145 二叉树的后序遍历(非递归)

    题目: 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路: 1 ...

  4. 【leetcode 145. 二叉树的后序遍历】解题报告

    前往二叉树的:前序,中序,后序 遍历算法 方法一:递归 vector<int> res; vector<int> postorderTraversal(TreeNode* ro ...

  5. Leetcode 145. 二叉树的后序遍历

    题目链接 https://leetcode-cn.com/problems/binary-tree-postorder-traversal/description/ 题目描述 给定一个二叉树,返回它的 ...

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

    题目描述 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路 后 ...

  7. LeetCode 145. 二叉树的后序遍历 (用栈实现后序遍历二叉树的非递归算法)

    题目链接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/ 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [ ...

  8. LeetCode 145 ——二叉树的后序遍历

    1. 题目 2. 解答 2.1. 递归法 定义一个存放树中数据的向量 data,从根节点开始,如果节点不为空,那么 递归得到其左子树的数据向量 temp,将 temp 合并到 data 中去 递归得到 ...

  9. LeetCode:二叉树的后序遍历【145】

    LeetCode:二叉树的后序遍历[145] 题目描述 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很 ...

随机推荐

  1. Android 小知识点笔记

    获取 view 的位置 View.getLocationInWindow(int[] location) 一个控件在其父窗口中的坐标位置 View.getLocationOnScreen(int[] ...

  2. ieda引入jstl后报错解决办法

    报错如下: HTTP Status 500 - The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in ei ...

  3. centos7 配置国内yum源

    配置清华大学镜像仓库 URL:https://mirrors.cnnic.cn/ CentOS 镜像使用帮助 https://mirrors.cnnic.cn/help/centos/ 建议先备份 C ...

  4. 【题解】[LuoguP3503]「BZOJ2086」[POI2010] Blocks

    题目描述 给出N个正整数a[1..N],再给出一个正整数k,现在可以进行如下操作:每次选择一个大于k的正整数a[i],将a[i]减去1,选择a[i-1]或a[i+1]中的一个加上1.经过一定次数的操作 ...

  5. 分布式事务与Seate框架(3)——Seata的AT模式实现原理

    前言 在上两篇博文(分布式事务与Seate框架(1)--分布式事务理论.分布式事务与Seate框架(2)--Seata实践)中已经介绍并实践过Seata AT模式,这里一些例子与概念来自这两篇(特别是 ...

  6. 【原创】SystemVerilog中的多态和虚方法

    封装可以隐藏实现细节,使代码模块化,继承可以扩展已经存在的代码模块,目的都是为了代码重用.多态是为了实现接口的重用.在SystemVerilog中,子类和父类之间多个子程序使用同一个名字的现象称为Sy ...

  7. Custom Controller CollectionQT样式自定义 001 :SliderLineEdit 滑动输入框

    主要是继承QLineEdit类重新实现其鼠标事件,建议禁用输入框默认的菜单项. SliderLineEdit 滑动输入框 参照图形平台 Adobe系列中属性输入框 做的样式,支持点击编辑和长按鼠标拖动 ...

  8. mysql_my.cnf文件详解

    以下是 my.cnf 配置文件参数解释:#*** client options 相关选项 ***##以下选项会被MySQL客户端应用读取.注意只有MySQL附带的客户端应用程序保证可以读取这段内容.如 ...

  9. 49、django工程(cookie+session)

    49.1.介绍: 1.cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要"保持状态",因此cookie就是在这样一个场景下诞生. cooki ...

  10. MindSpore模型精度调优实战:如何更快定位精度问题

    摘要:为大家梳理了针对常见精度问题的调试调优指南,将以"MindSpore模型精度调优实战"系列文章的形式分享出来,帮助大家轻松定位精度问题,快速优化模型精度. 本文分享自华为云社 ...