算法力扣刷题记录 三十七【二叉树层序遍历】

前言

二叉树递归遍历和二叉树迭代遍历 实现的前中后序遍历都归类深度搜索

广度搜索如何实现?一层结束,再继续下一层搜索:层序遍历。


一、题目阅读

【102.二叉树的层序遍历】
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例 1:
在这里插入图片描述

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

示例 2:

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

示例 3:

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

提示:

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

二、尝试实现

思路

(1)深度搜索中迭代循环使用的数据结构是栈,也是递归实现的原理。那么广度搜索(层序遍历)可不可以有数据结构用呢?如果还用栈,放入左右孩子时,无论是先入谁,出栈都不是按层出。所以得换。
(2)用队列怎么样?先把根节点入队,再入左孩子,再入右孩子。出队时,排序是层序结构。选定队列结构
(3)如果只是输出顺序,用队列把左右孩子不为空时,放入队列,按顺序出队就好了;但是结果需要按层划分数组,这就麻烦点。
(4)如果按sum求和,到第二层时sum=3,……到第n层是sum = 2^n -1。如果少了一边孩子,无法计数,依靠数量关系不好处理
(5)受迭代统一写法启发,如果每一层结束后面紧跟着null标记,从队列中取出空节点,说明一层结束,这就有了标志,nice。

代码实现

迭代实现:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result;	//先把返回值搞好queue<TreeNode*> que;	//定义一个队列if(root == nullptr) return result;que.push(root);	//如果第一层不是空,放入队列que.push(nullptr);//紧接着放入null,表示第一层结束。vector<int> levelrecord;//每一层的数组while(!que.empty()){TreeNode* cur = que.front();//获取队列出口元素if(cur!=nullptr){	//如果不为空,把左右孩子放入队列,前提左右孩子不为空时。if(cur->left) que.push(cur->left);if(cur->right)  que.push(cur->right);que.pop();	//取出出口元素levelrecord.push_back(cur->val);//放入当前层的数组中}else{	//如果取到空,说明这一层数组填好了。该往result里面放。que.pop();	//弹出空指针if(!levelrecord.empty()) result.push_back(levelrecord);	//如果该层不为空放入resultif(que.back() != nullptr){	//当队列还有元素,把层标记放进去;如果没有元素,说明已经到最后一层了,不用放入。que.push(nullptr);}levelrecord.clear();	//新的一层开始,清空上一层的存放}}return result;}
};

三、参考思路

二叉树层序遍历参考链接

学习内容

(1)借助队列,保存每一层的数据。如何实现?
(2)当一层的数组要放入result中时,用size来记录当前队列里元素的数量,这个数量是下一层的个数。只pop出size个元素放到当前层数组中。
(3)这样就不会出现两层元素混在一起。不知道这一层应该有几个元素。

对比思路总结:都是用队列来记录每一层的元素,但是如何知道每层元素个数方式不太一样:

  • 参考给出用size记录;
  • 个人想借助null标记表示一层结束。

代码实现

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result;queue<TreeNode*> que;if(root != nullptr) que.push(root);while(!que.empty()){int size = que.size();	//在还没遍历这一层时,先把这一层的元素个数记录下来。vector<int> levelrecord;while(size--){	//边遍历边放入下一层元素。TreeNode* top = que.front();que.pop();if(top->left) que.push(top->left);if(top->right) que.push(top->right);levelrecord.push_back(top->val);}result.push_back(levelrecord);}return result;}
};

总结

本文记录二叉树层序遍历(广度搜索)的实现。

  • 借助队列结构;
  • 在遍历之前,记录每一层的个数。避免两层元素混在一起。

补充

迭代法:直接用循环实现同一段代码的重复操作;
递归:通过自己调用自己,也实现某段代码的重复操作。
那么用递归来实现层序遍历呢?

递归思路

  • 每一层遍历都是重复的操作,所以把层遍历的while(size- -)改成函数,实现递归。获得一层的数组。
  • 在主函数的while中调用递归函数。

代码实现

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:void traversal(queue<TreeNode*>& q,vector<int>& levelrecord,int size){if(size == 0){	//确定回归的终止条件return;}//还不到回归的条件TreeNode* cur = q.front();q.pop();if(cur->left) q.push(cur->left);if(cur->right) q.push(cur->right);levelrecord.push_back(cur->val);size--;traversal(q,levelrecord,size);	//重复执行}vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result;queue<TreeNode*> que;if(root != nullptr) que.push(root);while(!que.empty()){int size =que.size();vector<int> vec;traversal(que,vec,size);result.push_back(vec);}return result;}
};

对比参考代码:
(1)在主函数中只调用一次递归函数,函数返回后,就可以return result。
(2)在递归函数order中:

  • 多层同时开展,先处理自己;再order左孩子;再order右孩子。
  • 如果没有新开一层,result已经放了该层数组
  • 如果新开一层,result需要push_back新数组。

流程如下
在这里插入图片描述

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:void order(TreeNode* cur,vector<vector<int>>& result,int depth){if(cur == nullptr) return;  //终止条件if(result.size() == depth ) result.push_back(vector<int> ());//新开一层,放入新数组,空的。result[depth].push_back(cur->val);order(cur->left,result,depth+1);//左孩子在下一层,所以result的下标应该+1order(cur->right,result,depth+1);//先左孩子再右孩子,可以使那一层从左到右。}vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> result;int depth = 0;//因为result数组下标从0开始order(root,result,depth);return result;}
};

(欢迎指正,转载标明出处)

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

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

相关文章

自然语言生成(NLG)- Transformer教程

近年来&#xff0c;自然语言生成&#xff08;Natural Language Generation&#xff0c;NLG&#xff09;技术的发展可谓是日新月异&#xff0c;而其中的核心技术之一便是Transformer。作为一种革命性的深度学习模型&#xff0c;Transformer改变了传统的自然语言处理&#xff08;…

Linux 关闭某个服务失败处理方法

在linux服务器上当我准备关闭Java应用程序时&#xff0c;出现下列错误&#xff1a; [rootVM-32-25-centos ~]# service eposGatewayService stop Application is running as root (UID 0). This is considered insecure. Unable to kill process 7080 如果不想重启主机&#…

如何在iPhone上恢复图片?5 个有效解决方案

对于许多iPhone用户来说&#xff0c;照片是存储在他们设备上的最重要的数据&#xff0c;因此丢失这些照片可能是一场灾难。 但是&#xff0c;即使您不小心删除了iPhone上的部分或全部图片&#xff0c;也可以将其取回。 我们将讨论如何在有或没有备份的情况下在iPhone上恢复已…

面试篇-Mysql-2+事务隔离级别的实现

文章目录 前言一、Mysql 的事务你了解吗二、你了解Mysql 的事务隔离级别吗&#xff1a;2.1 你知道Mysql 的脏读&#xff0c;不可重复读&#xff0c;幻读的问题吗&#xff1a;2.1.1 脏读&#xff1a;2.1.2 不可重复读&#xff1a;2.1.3 幻读&#xff1a; 2.2 对于并发场景下的脏…

Python使用策略模式和openpyxl库创建Excel文件并追加内容

from openpyxl import load_workbook# 数据数组 data [[1, 2, 3],[4, 5, 6],[7, 8, 9] ]# 打开现有的 Excel 文件 excel_file sheetApend_example.xlsx wb load_workbook(excel_file)# 选择要追加数据的工作表 sheet_name test_Sheet2 # 指定要追加数据的工作表名称 sheet…

用虚拟机,可以在x86的电脑上虚拟出arm的电脑吗

1.用虚拟机&#xff0c;可以在x86的电脑上虚拟出arm的电脑吗 是的&#xff0c;可以在x86的电脑上使用虚拟机技术虚拟出ARM架构的电脑。以下是通过虚拟机实现x86电脑上虚拟ARM电脑的几个关键步骤&#xff1a; 选择合适的虚拟化软件&#xff1a;通常&#xff0c;你可以使用如QE…

AI Agent满级进化!骑马种田、办公修图,样样精通,昆仑万维等发布通用Agent新框架

【导读】智能体又双叒叕进化了&#xff01;这次&#xff0c;什么游戏都能玩&#xff0c;什么软件都能操控了。 近日&#xff0c;昆仑万维携手北京智源人工智能研究院、新加坡南洋理工大学、北京大学等顶尖名校机构&#xff0c;联合提出了迄今为止第一个既能玩多种商业游戏又能…

Excel的Index+MATCH组合使用方法

INDEX函数 INDEX函数作用&#xff1a;用于从指定的单元格区域中返回特定行和列的值。 参数形式为&#xff1a;INDEX(array, row_num, [column_num]) array&#xff1a;必需。单元格区域或数组常量。 row_num&#xff1a;必需。要返回的值所在的行号。 [column_num]&#x…

【算法】【二分法】二分法详解

先给y总打一个广告。&#xff08;我这种废物收不到钱&#xff09; 本科时候就在打蓝桥杯玩玩算法&#xff0c;当时听朋友的一个刷题且涵盖教程的网站&#xff0c;ACWING。 www.acwing.com 里面好处是大部分基础算法都有&#xff0c;Y总的视频&#xff01; y总我的神&#xff01…

LLMs 入门实战系列

【LLMs 入门实战系列】 第一层 LLMs to Natural Language Processing (NLP) 第一重 ChatGLM-6B 【ChatGLM-6B入门-一】清华大学开源中文版ChatGLM-6B模型学习与实战 介绍&#xff1a;ChatGLM-6B 环境配置 和 部署 【ChatGLM-6B入门-二】清华大学开源中文版ChatGLM-6B模型微调…

行为模式9.策略模式------促销活动设计方案

行为型模式 模板方法模式&#xff08;Template Method Pattern&#xff09;命令模式&#xff08;Command Pattern&#xff09;迭代器模式&#xff08;Iterator Pattern&#xff09;观察者模式&#xff08;Observer Pattern&#xff09;中介者模式&#xff08;Mediator Pattern…

Rust入门实战 编写Minecraft启动器#5启动游戏

首发于Enaium的个人博客 好了&#xff0c;我们已经完成了所有的准备工作&#xff0c;现在我们可以开始编写启动游戏的代码了。 首先我们需要添加几个依赖。 model { path "../model" } parse { path "../parse" } download { path "../downlo…

ensp防火墙综合实验作业+实验报告

实验目的要求及拓扑图&#xff1a; 我的拓扑&#xff1a; 更改防火墙和交换机&#xff1a; [USG6000V1-GigabitEthernet0/0/0]ip address 192.168.110.5 24 [USG6000V1-GigabitEthernet0/0/0]service-manage all permit [Huawei]vlan batch 10 20 [Huawei]int g0/0/2 [Huawei-…

python 端口的转发

实现端口的转发 tcpsocket.py 对基础的socket进行了封装 import socketclass baseSocket:def service(host:str,port:int,maxSuspend:int)->socket: service_socket socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 创建 socket 对象service_socket.setso…

GPT的架构与应用 - Transformer教程

在过去的几年里&#xff0c;人工智能技术取得了巨大的进展&#xff0c;其中最引人注目的成就是生成式预训练变换器&#xff08;GPT&#xff09;的出现。GPT是一种基于Transformer架构的模型&#xff0c;已在自然语言处理&#xff08;NLP&#xff09;领域掀起了革命性变化。今天…

springboot vue 实现验证码

要在Spring Boot和Vue.js中实现验证码功能&#xff0c;可以按照以下步骤进行操作&#xff1a; 在Spring Boot项目中添加验证码相关的依赖。可以使用Google的Kaptcha库来生成验证码图片。在pom.xml中添加以下依赖&#xff1a; <dependency><groupId>com.github.pe…

安全开发--多语言基础知识

注释&#xff1a;还是要特别说明一下&#xff0c;想成为专业开发者不要看本文&#xff0c;本文是自己从业安全以来的一些经验总结&#xff0c;所有知识点也只限于网络安全这点事儿&#xff0c;再多搞不明白了。 开发语言 笼统的按照是否编译成机器码分类开发语言&#xff0c;…

Perl 语言开发(十二):面向对象编程,深入理解与实践

目录 1. 概述 2. 面向对象编程基础 2.1 类与对象的基本概念 3. Perl中的面向对象编程 3.1 定义类和对象 3.1.1 创建类 3.1.2 创建对象 3.2.1 访问器和修改器 3.3 继承 3.3.1 创建基类 3.3.2 创建子类 3.3.3 使用继承 3.4 多态 3.4.1 方法重写 3.4.2 动态绑定 4…

git常用命令及git分支

git常用命令及git分支 git常用命令设置用户签名初始化本地库查看本地库状态将文件添加到暂存区提交到本地库查看历史记录版本穿梭 git分支什么是分支分支的好处分支的操作查看分支创建分支切换分支合并分支合并冲突 git常用命令 设置用户签名 //设置用户签名 git config --gl…

linux-conda环境安装教程

Linux Conda 环境安装教程 本文档详细介绍了在 Linux 系统上安装和使用 Conda 环境的步骤。 1. 安装 Conda 1.1 下载 Anaconda 安装包 首先&#xff0c;访问 Anaconda 官方网站 并下载适用于 Linux 系统的 Anaconda 安装包。 或者使用以下命令直接从终端下载&#xff1a; …