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

devtools/2024/12/23 7:16:47/

一、题目描述

给你一棵二叉的根节点 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来存储后序遍历的结果。ArrayListJava集合框架中的一个可调整大小的数组实现,用于存储对象集合。

  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来存储遍历的结果,ArrayListJava集合框架中的一个可调整大小的数组实现,用于存储对象集合。

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

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

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

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

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


http://www.ppmy.cn/devtools/56986.html

相关文章

基于SpringBoot高校体育运动会管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

FPGA SATA高速存储设计

今天来讲一篇如何在fpga上实现sata ip&#xff0c;然后利用sata ip实现读写sata 盘的目的&#xff0c;如果需要再速度和容量上增加&#xff0c;那么仅仅需要增加sata ip个数就能够实现增加sata盘&#xff0c;如果仅仅实现data的读写整体来说sata ip设计比较简单&#xff0c;下面…

Batch Size 不同对evaluation performance的影响

目录 问题描述如果是bugbatch size的设置问题尝试使用GroupNorm解决batchsize不同带来的问题归一化的分类 参考文章 问题描述 深度学习网络训练时&#xff0c;使用较小的batch size训练网络后&#xff0c;如果换用较大的batch size进行evaluation&#xff0c;网络的预测能力会…

计算机毕业设计PyFlink+Spark+Hive民宿推荐系统 酒店推荐系统 民宿酒店数据分析可视化大屏 民宿爬虫 民宿大数据 知识图谱 机器学习

本科毕业设计(论文) 开题报告 学院 &#xff1a; 计算机学院 课题名称 &#xff1a; 民宿数据可视化分析系统的设计与实现 姓名 &#xff1a; 庄贵远 学号 &#xff1a; 2020135232 专业 &#xff1a; 数据科学与大数据技术 班级 &#xff1a; 20大数据本科2…

C++之STL(十)

1、适配器 2、函数适配器 #include <iostream> using namespace std;#include <algorithm> #include <vector> #include <functional>bool isOdd(int n) {return n % 2 1; } int main() {int a[] {1, 2, 3, 4, 5};vector <int> v(a, a 5);cou…

SQL小白超详细入门教程

SQL入门教程 一、SQL概述 SQL&#xff08;Structured Query Language&#xff09;是一种用于操作关系数据库&#xff08;如MySQL、Oracle、SQL Server等&#xff09;的编程语言。它是一门ANSI&#xff08;美国国家标准化组织&#xff09;的标准计算机语言&#xff0c;用于访问…

简明万年历编制(C语言)

简明万年历编制&#xff08;C语言 &#xff09; 编制万年历的要素&#xff1a; 农历公历对照&#xff0c;显示星期&#xff0c;农历干支年&#xff0c;当年生肖&#xff0c;国定节假日&#xff0c;寒天九九&#xff0c;暑日三伏&#xff0c;入梅出梅&#xff0c;节气时间&#…

机器学习原理和代码实现专辑

1. 往期文章推荐 1.【机器学习】图神经网络(NRI)模型原理和运动轨迹预测代码实现 2. 【机器学习】基于Gumbel-Sinkhorn网络的“潜在排列问题”求解 3. 【机器学习】基于Gumbel Top-k松弛技术的图形采样 4. 【机器学习】基于Softmax松弛技术的离散数据采样 5. 【机器学习】正则…