LeetCode题练习与总结:二叉树的层序遍历Ⅱ--107

2024-05-26 17:52

本文主要是介绍LeetCode题练习与总结:二叉树的层序遍历Ⅱ--107,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、题目描述

给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]

示例 2:

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

示例 3:

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

提示:

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

二、解题思路

 这个问题是关于如何对二叉树进行自底向上的层序遍历。我们可以使用一个队列来进行广度优先搜索(BFS),并使用一个变量来记录当前层的节点值。在遍历每一层的时候,我们使用一个双端队列(Deque)来存储当前层的节点值,这样我们就可以从双端队列的尾部开始遍历,从而实现自底向上的层序遍历。

算法步骤:

  1. 初始化一个空队列queue用于BFS,以及一个空的双端队列deque用于存储当前层的节点值。
  2. 如果root不为空,则将其加入queue
  3. 初始化一个变量level为0,用于标识当前层的奇偶性。
  4. queue不为空时,进行以下操作: a. 获取当前层的节点数量size(即queue的长度)。 b. 遍历当前层的节点,对于每个节点: i. 从queue中移除节点,并将其值加入deque的头部(如果level为偶数)或尾部(如果level为奇数)。 ii. 如果该节点的左子节点不为空,将其加入queue。 iii. 如果该节点的右子节点不为空,将其加入queue。 c. 将deque转换为列表,并加入结果列表result。 d. 将level加1,清空deque
  5. 返回结果列表result

三、具体代码

import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;public class Solution {public List<List<Integer>> levelOrderBottom(TreeNode root) {List<List<Integer>> result = new ArrayList<>();if (root == null) {return result;}Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);int level = 0;while (!queue.isEmpty()) {int size = queue.size();Deque<Integer> deque = new LinkedList<>();for (int i = 0; i < size; i++) {TreeNode node = queue.poll();if (node != null) {deque.offerLast(node.val);queue.offer(node.left);queue.offer(node.right);}}if (!deque.isEmpty()) {result.add(0, new ArrayList<>(deque));}}return result;}
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • levelOrderBottom 函数会对每个节点进行一次操作,其中 n 是树中节点的数量。
  • 因此,总的时间复杂度是 O(n)。
2. 空间复杂度
  • 空间复杂度主要取决于队列和双端队列中存储的节点数量。
  • 在最坏的情况下,树是完全不平衡的,例如每个节点都只有左子节点或者只有右子节点,此时队列和双端队列中存储的节点数量最多,为 O(n)。
  • 因此,总的空间复杂度是 O(n)。

综上所述,代码的时间复杂度是 O(n),空间复杂度也是 O(n),其中 n 是树中节点的数量。

五、总结知识点

  1. 队列(Queue)的使用:代码中使用了LinkedList类作为Queue的实现,用于在BFS中存储待遍历的节点。队列遵循先进先出(FIFO)的原则。

  2. 递归:虽然代码中没有直接使用递归,但BFS本质上是一种递归的过程,通过循环模拟递归的调用栈。

  3. 双端队列(Deque)的使用:代码中使用了LinkedList类作为Deque的实现,用于在每一层遍历时存储当前层的节点值。双端队列可以同时从两端添加或删除元素。

  4. 迭代与循环:使用while循环来迭代遍历树的每一层,直到队列为空。

  5. 条件语句:使用if-else语句来判断节点是否为空,以及判断队列是否为空。

  6. 数据结构转换:使用ArrayListLinkedList之间的转换,将Deque中的元素转换为一个List,然后添加到结果List中。

  7. 布尔变量的使用:使用布尔变量level来标志当前层的奇偶性,并在每层遍历后取反。

  8. 树节点的定义:代码中使用了TreeNode类来定义二叉树的节点,每个节点包含一个整数值和指向左右子节点的引用。

  9. 函数返回值levelOrderBottom函数返回一个包含多层的List<List<Integer>>,表示二叉树的自底向上的层序遍历结果。

  10. 边界条件的处理:在函数开始时检查root是否为空,如果为空则直接返回一个空列表。

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

这篇关于LeetCode题练习与总结:二叉树的层序遍历Ⅱ--107的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1005168

相关文章

关于C++中的虚拟继承的一些总结(虚拟继承,覆盖,派生,隐藏)

1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下: class A class B1:public virtual A; class B2:pu

随想录 Day 69 并查集 107. 寻找存在的路径

随想录 Day 69 并查集 107. 寻找存在的路径 理论基础 int n = 1005; // n根据题目中节点数量而定,一般比节点数量大一点就好vector<int> father = vector<int> (n, 0); // C++里的一种数组结构// 并查集初始化void init() {for (int i = 0; i < n; ++i) {father[i] = i;}

十五.各设计模式总结与对比

1.各设计模式总结与对比 1.1.课程目标 1、 简要分析GoF 23种设计模式和设计原则,做整体认知。 2、 剖析Spirng的编程思想,启发思维,为之后深入学习Spring做铺垫。 3、 了解各设计模式之间的关联,解决设计模式混淆的问题。 1.2.内容定位 1、 掌握设计模式的"道" ,而不只是"术" 2、 道可道非常道,滴水石穿非一日之功,做好长期修炼的准备。 3、 不要为了

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

Java注解详细总结

什么是注解?         Java注解是代码中的特殊标记,比如@Override、@Test等,作用是:让其他程序根据注解信息决定怎么执行该程序。         注解不光可以用在方法上,还可以用在类上、变量上、构造器上等位置。 自定义注解  现在我们自定义一个MyTest注解 public @interface MyTest{String aaa();boolean bbb()

tensorboard-----summary用法总结

Tensorflow学习笔记——Summary用法         最近在研究tensorflow自带的例程speech_command,顺便学习tensorflow的一些基本用法。 其中tensorboard 作为一款可视化神器,可以说是学习tensorflow时模型训练以及参数可视化的法宝。 而在训练过程中,主要用到了tf.summary()的各类方法,能够保存训练过程以及参数分布图并在

LeetCode--231 2的幂

题目 给定一个整数,编写一个函数来判断它是否是 2 的幂次方。 示例 示例 1:输入: 1输出: true解释: 20 = 1示例 2:输入: 16输出: true解释: 24 = 16示例 3:输入: 218输出: false class Solution {public:bool isPowerOfTwo(int n) {if (n <= 0) return fals

LeetCode--234 回文链表

题目 请判断一个链表是否为回文链表。 示例 示例 1:输入: 1->2输出: false示例 2:输入: 1->2->2->1输出: true /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val

LeetCode--220 存在重复元素 III

题目 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。 示例 示例 1:输入: nums = [1,2,3,1], k = 3, t = 0输出: true示例 2:输入: nums = [1,0,1,1], k = 1, t = 2输出: true示例

LeetCode--217 存在重复元素

题目 给定一个整数数组,判断是否存在重复元素。如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。 示例 示例 1:输入: [1,2,3,1]输出: true示例 2:输入: [1,2,3,4]输出: false示例 3:输入: [1,1,1,3,3,4,3,2,4,2]输出: true class Solution {p