LeetCode题练习与总结:二叉树的后序遍历--145

一、题目描述

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 

示例 1:

输入:root = [1,null,2,3]
输出:[3,2,1]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

提示:

  • 树中节点的数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100

二、方法一:递归方法

(一)解题思路

  1. 如果当前节点为空,返回。
  2. 对左子节点进行后序遍历。
  3. 对右子节点进行后序遍历。
  4. 访问当前节点,将其值加入结果列表。

(二)具体代码

import java.util.ArrayList;
import java.util.List;public class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();postorder(root, result);return result;}private void postorder(TreeNode node, List<Integer> result) {if (node == null) {return;}postorder(node.left, result);postorder(node.right, result);result.add(node.val);}
}

(三)时间复杂度和空间复杂度

1. 时间复杂度
  • 遍历每个节点:对于具有 N 个节点的二叉树,每个节点都会被访问一次。
  • 递归调用:每个节点都会进行两次递归调用(一次左子节点,一次右子节点)。
  • 结果添加:每个节点都会将其值添加到结果列表中,这是一个 O(1) 操作。

综上所述,时间复杂度为 O(N),其中 N 是二叉树中节点的数量。

2. 空间复杂度
  • 递归栈:递归实现需要使用栈来存储每次递归调用的信息。在最坏情况下,即树完全不平衡,每个节点都只有左子节点或只有右子节点,递归栈的深度会是 O(N)。
  • 结果列表:结果列表存储了所有节点的值,因此空间复杂度为 O(N)。

综上所述,空间复杂度为 O(N),其中 N 是二叉树中节点的数量。

注意:在实际应用中,递归调用栈的深度通常不会超过 logN,因为大多数二叉树的形状都趋于平衡。但是在分析空间复杂度时,我们通常考虑最坏情况。

(四)总结知识点

  1. 递归:这是一种编程技巧,其中一个函数直接或间接地调用自身。在这个代码中,postorder 函数递归地调用自身来遍历二叉树的左子树和右子树。

  2. 二叉树遍历:代码实现了二叉树的后序遍历。后序遍历是一种深度优先遍历策略,其中节点的遍历顺序是:左子树、右子树、根节点。

  3. 二叉树节点定义:代码中使用了TreeNode类来定义二叉树的节点,每个节点包含一个整数值val以及指向其左子节点和右子节点的指针leftright

  4. 列表(ArrayList):代码中使用ArrayList来存储后序遍历的结果。ArrayList是Java集合框架中的一个可调整大小的数组实现,用于存储对象集合。

  5. 函数参数传递:代码中的postorder函数接受两个参数,一个是TreeNode类型的节点,另一个是List<Integer>类型的结果列表。这展示了如何在函数间传递复杂类型(如自定义类和集合)的参数。

  6. 基本数据类型:代码中的int类型用于存储节点的值,这是Java的基本数据类型之一,用于表示整数。

  7. 条件语句:代码中使用了if语句来检查当前节点是否为null,这是Java中的条件语句,用于根据条件执行不同的代码路径。

  8. 函数返回值postorder函数是一个void函数,它不返回任何值,而是直接修改传入的结果列表。这展示了Java中函数可以有不同的返回类型,包括无返回值的void类型。

  9. 异常处理:虽然这个代码中没有显式的异常处理,但是在Java中,递归调用可能会引发StackOverflowError异常,如果递归深度过大,超出了栈的容量。在实际应用中,可能需要考虑异常处理来确保程序的健壮性。

三、方法二:迭代方法

(一)解题思路

  1. 使用一个栈来存储节点,一个列表来存储访问顺序。
  2. 将根节点和空节点入栈,然后进行循环。
  3. 在循环中,弹出栈顶节点,如果栈不为空且栈顶节点不等于上一个访问的节点,则将节点重新入栈,并将其右子节点和左子节点依次入栈(这样可以保证左子节点先被访问)。
  4. 如果栈为空或栈顶节点等于上一个访问的节点,则访问该节点,将其值加入结果列表。

(二)具体代码

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;public class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();Stack<TreeNode> stack = new Stack<>();TreeNode prev = null;if (root != null) {stack.push(root);}while (!stack.isEmpty()) {TreeNode curr = stack.peek();if (prev == null || prev.left == curr || prev.right == curr) {if (curr.left != null) {stack.push(curr.left);} else if (curr.right != null) {stack.push(curr.right);} else {stack.pop();result.add(curr.val);}} else if (curr.left == prev) {if (curr.right != null) {stack.push(curr.right);} else {stack.pop();result.add(curr.val);}} else if (curr.right == prev) {stack.pop();result.add(curr.val);}prev = curr;}return result;}
}

(三)时间复杂度和空间复杂度

1. 时间复杂度
  • 每个节点处理:对于具有 N 个节点的二叉树,每个节点都会被处理一次。
  • 循环迭代:代码中使用了一个循环,循环的次数与树的节点数相同。

综上所述,时间复杂度为 O(N),其中 N 是二叉树中节点的数量。

2. 空间复杂度
  • 栈空间:迭代实现需要使用栈来存储节点。在最坏情况下,即树完全不平衡,每个节点都只有左子节点或只有右子节点,栈的深度会是 O(N)。
  • 结果列表:结果列表存储了所有节点的值,因此空间复杂度为 O(N)。

综上所述,空间复杂度为 O(N),其中 N 是二叉树中节点的数量。

注意:在实际应用中,迭代实现的空间复杂度通常不会超过 logN,因为大多数二叉树的形状都趋于平衡。但是在分析空间复杂度时,我们通常考虑最坏情况。

(四)总结知识点

  1. 迭代与栈的使用:代码使用了一个栈Stack来迭代地遍历二叉树。栈是一种后进先出(LIFO)的数据结构,用于在迭代过程中存储待处理的节点。

  2. 二叉树的后序遍历:后序遍历是一种二叉树的遍历方式,遍历顺序为:左子树、右子树、根节点。代码通过迭代的方式实现了这一遍历。

  3. 条件判断与分支:代码中使用了多个if语句来进行条件判断,根据不同的条件执行不同的代码块,以实现遍历的逻辑。

  4. 循环结构:代码使用了一个while循环来不断地从栈中取出节点进行处理,直到栈为空,即所有节点都被遍历完毕。

  5. 节点关系与指针:代码中使用了prev变量来跟踪上一个访问的节点,以便确定当前节点的左右子节点是否已经被访问过。

  6. 链表与列表:代码使用了ArrayList来存储遍历的结果,ArrayList是Java集合框架中的一个可调整大小的数组实现,用于存储对象集合。

  7. 自定义数据类型:代码中使用了TreeNode自定义类来表示二叉树的节点,每个节点包含一个整数值val以及指向其左子节点和右子节点的指针leftright

  8. 函数定义与返回值:代码定义了postorderTraversal函数,它接受一个TreeNode类型的参数(根节点),并返回一个List<Integer>类型的结果(后序遍历的节点值列表)。

  9. 基本数据类型与操作:代码中使用了int类型来存储节点的值,以及基本的赋值和比较操作。

  10. 异常处理:虽然这个代码中没有显式的异常处理,但是在Java中,使用栈时可能会遇到异常情况,例如栈溢出。在实际应用中,可能需要考虑异常处理来确保程序的健壮性。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/367254.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2002-2022年各省老年人口抚养比(人口抽样调查)数据

2002-2022年各省老年人口抚养比(人口抽样调查)数据 1、时间&#xff1a;2002-2022年 2、指标&#xff1a;老年人口抚养比 3、来源&#xff1a;国家统计局、统计年鉴 4、范围&#xff1a;31省&#xff0c; 5、缺失情况&#xff1a;无缺失&#xff0c;其中2010年的值取2009、…

Swift 中强大的 Key Paths(键路径)机制趣谈(下)

概览 在上一篇博文 Swift 中强大的 Key Paths(键路径)机制趣谈(上)中,我们介绍了 Swift 语言中键路径机制的基础知识,并举了若干例子讨论了它的一些用武之地。 而在本文中我们将再接再厉,继续有趣的键路径大冒险,为 KeyPaths 画上一个圆满的句号。 在本篇博文中,您将…

JavaScript之深入对象,详细讲讲构造函数与常见内置构造函数

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;我是前端菜鸟的自我修养&#xff01;今天给大家详细讲讲构造函数与常见内置构造函数&#xff0c;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;原创不易&#xff0c;如果能帮助到带大家&#xff0c;欢迎…

笔记:Git学习之应用场景和使用经验

目标&#xff1a;整理Git工具的应用场景和使用经验 一、开发环境 Git是代码版本控制工具&#xff1b;Github是代码托管平台。 工具组合&#xff1a;VSCode Git 需要安装的软件&#xff1a;vscode、Git 其中vscode需要安装的插件&#xff1a;GitLens、Git History 二、应用…

Unity编辑器工具---版本控制与自动化打包工具

Unity - 特殊文件夹【作用与是否会被打包到build中】 Unity编辑器工具—版本控制与自动化打包工具&#xff1a; 面板显示&#xff1a;工具包含一个面板&#xff0c;用于展示软件的不同版本信息。版本信息&#xff1a;面板上显示主版本号、当前版本号和子版本号。版本控制功能…

单目行车测距摄像系统(单目测距-行车)

单目行车测距摄像系统是一种利用单个摄像头实现车辆行驶中前方障碍物距离测量的技术。该系统通过计算机视觉算法&#xff0c;能够实时分析摄像头捕捉的图像&#xff0c;精确计算出车辆与前方物体之间的距离&#xff0c;对于自动驾驶、高级驾驶辅助系统&#xff08;ADAS&#xf…

【探索Linux】P.36(传输层 —— TCP协议段格式)

阅读导航 引言一、TCP段的基本格式二、控制位详细介绍三、16位接收窗口大小⭕窗口大小的作用⭕窗口大小的限制⭕窗口缩放选项⭕窗口大小的更新⭕窗口大小与拥塞控制 四、紧急指针温馨提示 引言 在上一篇文章中&#xff0c;我们深入探讨了一种无连接的UDP协议&#xff0c;它以其…

《新华日报》理论版报刊简介及投稿邮箱

《新华日报》理论版报刊简介及投稿邮箱 《新华日报》是中国共产党在抗日战争时期和解放战争初期创办的大型机关报&#xff0c;1949 年 4 月在南京复刊&#xff0c;1952 年成为中国共产党江苏省委机关报&#xff0c;现为中共江苏省委直属事业单位。 该报纸的理论版&#xff08;…

记录前端发现问题之 mock接口无返回数据导致所有后续接口调用报错:网络异常

1. 背景 就更新了代码&#xff0c;发现新涉及的页面&#xff0c;切换tab 之后会报错网络异常&#xff0c;再次切换其他没涉及的功能页面&#xff0c;继续报错网络异常 测试环境&#xff1a;纯前端代码&#xff0c;后端是前端mock的数据&#xff0c;仅供demo 2. 问题报错 手动…

开箱机视觉系统大揭秘:如何轻松辨别千差万别的包装?

在现代物流仓储领域&#xff0c;开箱机作为提升作业效率的关键设备&#xff0c;正日益受到行业的重视。而开箱机的视觉系统更是其十分强大&#xff0c;能够准确辨认不同包装&#xff0c;确保物流作业的高效与准确。与星派深入探究一下开箱机视觉系统是如何工作的&#xff0c;以…

女生读中职,选择什么专业最吃香!

自《国家职业教育改革实施方案》颁布实施以来,中国职业教育的改革和发展已取得显著进展。目前,我国已建立起世界上规模最大的职业教育体系,中高职学校每年培养约1000万高素质技术技能人才,职业教育实现了历史性的跨越。对于那些不愿加入“千军万马过独木桥”的高考竞争大军,初中…

Firewalld防火墙基础

Firewalld 支持网络区域所定义的网络连接以及接口安全等级的动态防火墙管理工具 支持IPv4、IPv6防火墙设置以及以太网桥 支持服务或应用程序直接添加防火墙规则接口 拥有两种配置模式 运行时配置&#xff1a;临时生效&#xff0c;一旦重启或者重载即不生效 永久配置&#xff1a…

华三多台交换机堆叠配置(环形组网)

组网架构 配置步骤 SW1的配置&#xff1a; irf member 1 priority 32 设置master的优先级为32 interfacec range Ten-GigabitEthernet1/0/49 to Ten-GigabitEthernet1/0/50 shutdown 关闭上述接口&#xff08;将其加入到堆叠口之前需要关闭&#xff0c;否则无法加入&a…

机器学习 - 实现KNN对图像有监督学习的 分类算法 (一)【原理】

一、KNN算法介绍&#xff1a; KNN 算法&#xff0c;或者称 k最邻近算法&#xff0c;是 有监督学习 中的 分类算法 。它可以用于分类或回归问题&#xff0c;但它通常用作分类算法。 KNN &#xff08;K-Nearest Neighbor&#xff09;算法是机器学习算法中最基础、最简单的算法之一…

“不喝鸡汤 不诉离殇”华火电燃灶用实力引领烹饪灶具发展

在这个快节奏的时代&#xff0c;我们常常被各种厨房电器的鸡汤所包围&#xff0c;并悄悄的告诉我们厨房生活是美好与温暖的&#xff0c;但面对现实中的挑战与困难时&#xff0c;常常表现出选择性失明&#xff1b;那些隐藏在传统厨房烹饪环境下的危机&#xff0c;就像是慢性的毒…

[Python学习篇] Python函数

定义函数 语法&#xff1a;使用关键字 def def 函数名(参数): 代码1 代码2 ...... 调用函数 语法&#xff1a; 函数名(参数) 注意&#xff1a;不同的需求&#xff0c;参数可有可无。在Python中&#xff0c;函数必须先定义后使用 示例&#xff1a; # 定义函数 d…

华为仓颉编程语言

目录 一、引言 二、仓颉编程语言概述 三、技术特征 四、应用场景 五、社区支持 六、结论与展望 一、引言 随着信息技术的快速发展&#xff0c;编程语言作为软件开发的核心工具&#xff0c;其重要性日益凸显。近年来&#xff0c;华为公司投入大量研发资源&#xff0c;成功…

小白学python(第三天)

小伙伴&#xff0c;大家好呀&#xff0c;昨天的内容吸收的好&#xff1f;昨天有小伙伴私信我&#xff0c;建议我在博文中加点练习题&#xff0c;可以看出这位童鞋很想学好这门语言哈&#xff0c;那我也尽量满足大家的要求。 从控制台输入 语法格式&#xff1a; 变量名 input…

C++基础(三):C++入门(二)

上一篇博客我们正式进入C的学习&#xff0c;这一篇博客我们继续学习C入门的基础内容&#xff0c;一定要学好入门阶段的内容&#xff0c;这是后续学习C的基础&#xff0c;方便我们后续更加容易的理解C。 目录 一、内联函数 1.0 产生的原因 1.1 概念 1.2 特性 1.3 面试题 …