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

news2024/11/23 2:50:37

一、题目描述

给你一棵二叉树的根节点 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.coloradmin.cn/o/1888465.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于批量采集1688商品主图及链接的方式:软件采集/1688官方API接口数据采集

关于批量采集&#xff0c;我们通常用到的是软件 采集&#xff0c;或者通过1688官方API数据采集的形式&#xff1a;用户输入一组1688商品ID&#xff0c;一行一个&#xff0c;流程会自动逐个打开对应的1688商品详情页&#xff0c;采集主图的所有链接。 结果保存为表格的一行&…

人工智能-NLP简单知识汇总01

人工智能-NLP简单知识汇总01 1.1自然语言处理的基本概念 自然语言处理难点&#xff1a; 语音歧义句子切分歧义词义歧义结构歧义代指歧义省略歧义语用歧义 总而言之&#xff1a;&#xff01;&#xff01;语言无处不歧义 1.2自然语言处理的基本范式 1.2.1基于规则的方法 通…

JDBC【封装工具类、SQL注入问题】

day54 JDBC 封装工具类01 创建配置文件 DBConfig.properties driverNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/qnz01?characterEncodingutf8&serverTimezoneUTC usernameroot passwordroot新建配置文件&#xff0c;不用写后缀名 创建工具类 将变…

【Linux】TCP协议【下三】{面向字节流/粘包问题/TCP异常情况/文件和Socket}

文章目录 7.面向字节流TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09; 8.粘包问题9.TCP异常情况10.再谈文件和socket的关系 7.面向字节流 创建一个TCP的socket, 同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区;一个链接一对发收缓…

day09了 加油

浅拷贝 指向同一个地址空间 右边不可取地址 左边一定是到了具体的位置 右值引用std&#xff1a;&#xff1a; move 相信大家默认构造函数都没有问题&#xff0c;所以就不贴例子了 浅拷贝构造函数 只负责复制地址&#xff0c;而不是真的把完整的内存给它 #include <iostre…

Qt——升级系列(Level Seven):事件、文件

目录 Qt事件 事件介绍 事件的处理 按键事件 鼠标事件 定时器 事件分发器 事件过滤器 Qt文件 Qt文件概述 输入输出设备类 文件读写类 文件和目录信息类 Qt事件 事件介绍 事件是应⽤程序内部或者外部产⽣的事情或者动作的统称。在 Qt 中使⽤⼀个对象来表⽰⼀个事件。所有的 Qt …

Linux修炼之路之进程概念,fork函数,进程状态

目录 一&#xff1a;进程概念 二&#xff1a;Linux中的进程概念 三&#xff1a;用getpid(),getppid()获取该进程的PID,PPID 四&#xff1a;用fork()来创建子进程 五&#xff1a;操作系统学科的进程状态 六&#xff1a;Linux中的进程状态 接下来的日子会顺顺利利&#xf…

WordPress网站添加插件和主题时潜在危险分析

WordPress 最初只是一个简单的博客软件&#xff0c;现在据估计为全球前 1000 万个网站中的 30% 提供支持。WordPress受欢迎的因素之一是可以轻松创建插件和主题来扩展它并提供比默认设置更多的功能。 目前&#xff0c;WordPress 网站列出了 56,000 多个插件以及数千个主题。插件…

提升用户体验之requestAnimationFrame实现前端动画

requestAnimationFrame是什么 MDN官方解释 解析这段话&#xff1a; 1、那么浏览器重绘是指什么呢&#xff1f; ——大多数电脑的显示器刷新频率是60Hz&#xff0c;1000ms/6016.66666667ms的时间刷新一次 2、重绘之前调用指定的回调函数更新动画&#xff1f; ——requestAnima…

机器学习辅助的乙醇浓度检测

目录 1.为什么要机器学习 2. 神经网络一般组成 3.BP神经网络工作过程 4.评价指标 5.实操代码 1.为什么要用机器学习 人工分析大量的谐振模式&#xff0c;建立各种WGM的响应与未知目标之间的关系&#xff0c;是一个很大的挑战。机器学习(ML)能够自行识别全谱的全部特征。作为…

Python深度理解系列之【排序算法——冒泡排序】

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️木道寻的主页 文章目录 &#x1f525;前言&#x1f680;冒泡排序python实现算法实现图形化算法展示 ⭐️⭐️⭐️总结 &#x1f525;前…

ONLYOFFICE8.1版本桌面编辑器简单测评

ONLYOFFICE官网链接&#xff1a;在线PDF查看器和转换器 | ONLYOFFICE ONLYOFFICE介绍&#xff1a;https://www.onlyoffice.com/zh/office-suite.aspx OnlyOffice 是一款免费且开源的 Office 协作办公套件&#xff0c;支持桌面端和移动端等多平台&#xff0c;由一家领先的 IT 公…

OpenStack开源虚拟化平台(二)

目录 三、对象存储服务Swift&#xff08;一&#xff09;Swift特性&#xff08;二&#xff09;应用场景&#xff08;三&#xff09;Swift主要组件&#xff08;四&#xff09;Swift基本原理&#xff08;五&#xff09;实例分析 四、镜像服务Glance&#xff08;一&#xff09;Glan…

如何在 Java 应用中使用 Jedis 客户端库来实现 Redis 缓存的基本操作

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

图解 Kafka 架构

写在前面 Kafka 是一个可横向扩展&#xff0c;高可靠的实时消息中间件&#xff0c;常用于服务解耦、流量削峰。 好像是 LinkedIn 团队开发的&#xff0c;后面捐赠给apache基金会了。 kafka 总体架构图 Producer&#xff1a;生产者&#xff0c;消息的产生者&#xff0c;是消息的…

不改代码,实现web.config或app.config的连接字符串加密解密

目的&#xff1a;加密字符串&#xff0c;防止明文显示。 好处&#xff1a;不用修改代码&#xff0c;微软自带功能&#xff0c;自动解密。 web.config 参考相关文章&#xff1a; Walkthrough: Encrypting Configuration Information Using Protected Configuration | Microso…

本地通过ollama下载模型,并使用python跑这个本地模型

1&#xff0c;这是ollama地址&#xff0c;下载对应的安装包 https://ollama.com/?viaurlainavpro.com 2&#xff0c;下载完直接安装即可&#xff0c;安装完后&#xff0c;winr打开cmd&#xff0c;出现这个&#xff0c;基本就妥了 3&#xff0c;这里我们需要去下载模型&#x…

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

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

【NLP学习笔记】load_dataset加载数据

除了常见的load_dataset(<hf上的dataset名>)这种方式加载HF上的所有数据外&#xff0c;还有其他custom的选项。 加载HF上部分数据 from datasets import load_dataset c4_subset load_dataset("allenai/c4", data_files"en/c4-train.0000*-of-01024.js…