算法——队列+宽搜(BFS)

队列这种数据结构大都服务于一个算法——宽搜(BFS)。宽搜还可以运用到二叉树、图、迷宫最短路径问题、拓扑排序等等

N叉数的层序遍历

N叉树的层序遍历

题目解析

  • 给定一个 N 叉树,返回其节点值的_层序遍历_。(即从左到右,逐层遍历)。
  • 树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

算法原理

层序遍历(BFS宽度优先遍历):当我们遍历完 1、3、2、4时,要回过头看拓展3的子节点情况。这一过程属于先进先出的——队列这一数据结构可以解决,以二维数组的形式返回。
image.png

  1. 搞一个队列,如果根节点不为空,先让根节点入队。然后开始while循环,当队列不空的时候,把队头元素1拿出来,让队头元素的子节点2、3、4入队。接着继续将队头元素拿出来,让队头元素2的子节点5、6入队.接着将队头元素3拿出来,7入队,4拿出来,8入队。。继续拿出5、6、7、8(他们都没有子节点,就直接拿出即可)image.png

· image.png

  1. 这里还有一个问题,在一次访问遍历节点时,如果出现不同层的节点元素进入,该怎样统计呢?我们这里只需要设置一个变量,统计元素个数。即当1进入队列时,计数为1;当1出队列时,2、3、4进入。此时个数为3就令变量为3。第二层出完时。第三层四个元素已经全部进入,令变量为4。

代码实现

/*
// Definition for a Node.
class Node {
public:int val;vector<Node*> children;Node() {}Node(int _val) {val = _val;}Node(int _val, vector<Node*> _children) {val = _val;children = _children;}
};
*/class Solution 
{
public:vector<vector<int>> levelOrder(Node* root) {vector<vector<int>> ret; // 记录最终结果queue<Node*> q; // 层序遍历需要的队列if(root == nullptr) return ret;q.push(root);while(q.size()){int sz = q.size(); // 先求出本层元素的个数vector<int> tmp; // 统计本层的节点for(int i = 0; i < sz; i++){Node* t = q.front();   //拿出队头元素q.pop();tmp.push_back(t->val); //将节点加入到最终返回的数组中for(Node* child : t->children) // 遍历它的子节点,让下⼀层结点⼊队{if(child != nullptr)q.push(child);}}ret.push_back(tmp);}return ret;}
};

二叉树的锯齿形层序遍历

二叉树的锯齿形层序遍历

题目解析

image.png

算法原理

解法:层序遍历
在层序遍历的结果存到最终返回结果之前,奇数行直接存入要返回的ret里,偶数行多执行一个逆序返回到ret里面即可。
image.png

代码实现

/*** 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>> zigzagLevelOrder(TreeNode* root) {vector<vector<int>> ret;if(root == nullptr) return ret;queue<TreeNode*> q;q.push(root);int level = 1;while(q.size()){int sz = q.size();vector<int> tmp;for(int i = 0; i < sz; i++){auto t = q.front();q.pop();tmp.push_back(t->val);if(t->left) q.push(t->left);if(t->right) q.push(t->right);}// 判断是否逆序if(level % 2 == 0) reverse(tmp.begin(), tmp.end());ret.push_back(tmp);level++;}return ret;}
};

二叉树最大宽度

二叉树最大宽度

题目解析

  • 给你一棵二叉树的根节点 root ,返回树的 最大宽度
  • 树的 最大宽度 是所有层中最大的 宽度
  • 每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null 节点,这些 null 节点也计入长度。image.png

算法原理

解法一:硬来层序遍历
统计每⼀层的最⼤宽度,我们优先想到的就是利⽤层序遍历,把当前层的结点全部存在队列⾥⾯,利⽤队列的⻓度来计算每⼀层的宽度,统计出最⼤的宽度。但是,由于空节点也是需要计算在内的。因此,我们可以选择将空节点也存在队列⾥⾯。

当遍历到最后一层时,最后一层宽度为7。可以定义一个empty(统计null个数),从最后一层第一个位置开始扫描,遇到null节点+1,直至遇到下一个有效数字。停止,计算出宽度。然后再将empty置空为0,然后继续向后遍历,因为后面没有真实数字节点,所以最后一个null不计入宽度里。
image.png

但是这里会超时,会有一种极端情况。将3000个节点平均分(题中给的数据范围为3000),如果还按照我们上述计算宽度的算法,那么最后一层将达到21000,这样是大大超出内存的。image.png

解法二:利用数组存储二叉树,给节点编号
树我们不仅有链式存储,还有顺序存储。我们可以通过给二叉树节点编号,通过公式计算给他的子节点编号(两个公式区别就是头结点从1开始计数还是从0开始计数)
image.pngimage.png

  1. 创建一个队列,此时队列里就不仅仅存储节点,我们即存他的节点,也存他的编号。计算宽度方法就是拿出这个队的队头,拿出这个队的对尾,下标相减+1即可;这样就不需要处理空节点了。(有的容器只能访问队头,不能访问队尾,这对于计算宽度就有些麻烦,我们可以用数组模拟队列)image.png

  2. 细节问题:下标有可能溢出。再次回到解法一遇到的极端情况,在那种情况下,最后一层的最后一个节点编号为21500-1.这个数字是任何一个数据类型都存不下的。但是当我们相减之后算出最后结果也是正确的。因为我们的数据存储是一个环形存储,我们最终计算的是距离(绿色部分),这个距离是不会溢出的,所以结果是正确的。我们C++用unsigned int存储就不会报错了image.png

代码实现

/*** 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:int widthOfBinaryTree(TreeNode* root) {vector<pair<TreeNode*, unsigned int>> q; // ⽤数组模拟队列q.push_back({root, 1});unsigned int ret = 0;while(q.size()){// 先更新这⼀层的宽度auto& [x1, y1] = q[0];auto& [x2, y2] = q.back();ret = max(ret, y2 - y1 + 1);// 让下⼀层进队vector<pair<TreeNode*, unsigned int>> tmp; // 让下⼀层进⼊这个队列for(auto& [x, y] : q){if(x->left) tmp.push_back({x->left, y * 2});if(x->right) tmp.push_back({x->right, y * 2 + 1});}q = tmp;}
return ret;}
};

在每个树行中找最大值

在每个树行中找最大值

题目解析

给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

算法原理

利用层序遍历,统计出每一层的最大值。

代码实现

/*** 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<int> largestValues(TreeNode* root) {vector<int> ret;if(root == nullptr) return ret;queue<TreeNode*> q;q.push(root);while(q.size()){int sz = q.size();int tmp = INT_MIN;  //初始化为无穷小,让数字与tmp比较for(int i = 0; i < sz; i++){auto t = q.front(); //拿出队头元素q.pop();            //干掉队头元素tmp = max(tmp, t->val);  //更新这一层最大值if(t->left) q.push(t->left); //让其子节点入队if(t->right) q.push(t->right);}ret.push_back(tmp);}return ret;}
};

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

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

相关文章

使用Wireshark进行网络流量分析

目录 Wireshark是什么&#xff1f; 数据包筛选 筛选指定ip 使用逻辑运算符筛选 HTTP模式过滤 端口筛选 协议筛选 包长度筛选 数据包搜索 数据流分析 数据包导出 Wireshark是什么&#xff1f; 通过Wireshark&#xff0c;我们可以捕获和分析网络数据包&#xff0c;查看…

【Maven】工程依赖下载失败错误解决

在使用 Maven 构建项目时&#xff0c;可能会发生依赖项下载错误的情况&#xff0c;主要原因有以下几种&#xff1a; 下载依赖时出现网络故障或仓库服务器宕机等原因&#xff0c;导致无法连接至 Maven 仓库&#xff0c;从而无法下载依赖。 依赖项的版本号或配置文件中的版本号错…

SPI

一、简介 SPI是一种同步、全双工、主从式接口。来自主机或从机的数据在 时钟上升沿或下降沿同步。主机和从机可以同时传输数据。SPI接 口可以是3线式或4线式。 MOSI(Master Output Slave Input) – 主设备输出/从设备输入信号&#xff1b;MISO(Master Input Slave Output) – 主…

经典卷积神经网络-ResNet

经典卷积神经网络-ResNet 一、背景介绍 残差神经网络(ResNet)是由微软研究院的何恺明、张祥雨、任少卿、孙剑等人提出的。ResNet 在2015 年的ILSVRC&#xff08;ImageNet Large Scale Visual Recognition Challenge&#xff09;中取得了冠军。残差神经网络的主要贡献是发现了…

Nginx 反向代理负载均衡

Nginx 反向代理负载均衡 普通的负载均衡软件&#xff0c;如 LVS&#xff0c;其实现的功能只是对请求数据包的转发、传递&#xff0c;从负载均衡下的节点服务器来看&#xff0c;接收到的请求还是来自访问负载均衡器的客户端的真实用户&#xff1b;而反向代理就不一样了&#xf…

Android混淆那些事

前言 作为一个Android开发&#xff0c;大家或多或少都有一些关于混淆的了解&#xff08;毕竟披个纱布也比裸奔要好的多吧&#xff09;。混淆的概念虽然容易理解&#xff0c;但相信大多数开发可能还是在网上搜索通用配置后通过C-V大法接入到自己的项目中&#xff0c;这也使得混…

canvas绘制网格线示例

查看专栏目录 canvas示例教程100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

docker 部署教学版本

文章目录 一、docker使用场景及常用命令1&#xff09;docker使用场景2&#xff09;rocky8(centos8)安装 docker3&#xff09;docker 常用命令补充常用命令 二、 单独部署每个镜像&#xff0c;部署spring 应用镜像推荐&#xff08;2023-12-18&#xff09;1、 安装使用 mysql1.1 …

高可用解决方案 Keepalived 概述

概述 Keepalived 介绍 Keepalived 是 Linux 下一个轻量级别的高可用解决方案&#xff0c;通过 **VRRP 协议&#xff08;虚拟路由冗余协议&#xff09;**来实现服务或者网络的高可用&#xff0c;可以利用其来解决单点故障。 起初是为 LVS 设计的&#xff0c;一个 LVS 服务会有 …

计算机毕业论文内容参考|基于智能搜索引擎的图书管理系统的设计与实现

文章目录 摘要前言绪论课题背景国内外现状与趋势课题内容相关技术与方法介绍系统分析系统设计系统实现系统测试总结与展望摘要 本文介绍了基于智能搜索引擎的图书管理系统的设计与实现。该系统旨在提供一个高效、智能化的图书管理平台,帮助用户更快、更准确地找到所需的图书资…

2024年PMP报考需要什么条件?怎么报名?

一、PMP是什么 PMP 是项目管理的入门级证书&#xff0c;全称是项目管理专业人士资格认证&#xff0c;由美国项目管理协会&#xff08;PMI&#xff09;举办的&#xff0c;受到全球200多个国家的认可&#xff0c;从1999 年到现在已经有20多年发展历史了。 顾名思义&#xff0c;…

【大数据面试知识点】分区器Partitioner:HashPartitioner、RangePartitioner

Spark HashParitioner的弊端是什么&#xff1f; HashPartitioner分区的原理很简单&#xff0c;对于给定的key&#xff0c;计算其hashCode&#xff0c;并除于分区的个数取余&#xff0c;如果余数小于0&#xff0c;则用余数分区的个数&#xff0c;最后返回的值就是这个key所属的…

阶段十-分布式-nginx服务器

一、Nginx简介 Nginx 是高性能的 HTTP 和反向代理的服务器&#xff0c;处理高并发能力是十分强大的&#xff0c;能经受高负载的考验,有报告表明能支持高达 50,000 个并发连接数。tomcat并发数量理论值是500&#xff0c;实际也就300左右。 1.2 正向代理 正向代理代理的是客户…

世微 DW01 4.2V锂电池保护电路芯片 专业电源管理芯片

一、 描述 DW01A 是一个锂电池保护电路&#xff0c;为避免锂电池因过充电、过放电、电流过大导致电池寿命缩短或电池被损坏而设计的。它具有高精确度的电压检测与时间延迟电路。 二、 主要特点 工作电流低&#xff1b; 过充检测 4.3V&#xff0c;过充释放 4.05V&#xff1b; 过…

缅怀一代传奇!TVP创始委员陈皓与他的《左耳听风:传奇程序员练级攻略》

引言 中文技术圈时常被一种浮躁所困扰。互联网企业历经跑马圈地的红利期后&#xff0c;开始在精细化运营的路上艰难求索&#xff1b;圈子里的程序员们&#xff0c;也被日益放缓的业务需求和不断内卷的行业态势所影响&#xff0c;职业困境、年龄危机成了老生常谈的话题。 成长往…

three.js 多通道组合

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div style"border: 1px so…

AI大模型引领未来智慧科研暨ChatGPT在地学、GIS、气象、农业、生态、环境等领域中的高级应用

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

C语言中关于while语句的理解以及getchar和putchar

while是一个循环语句&#xff0c;关于while的一些理解可以看下面这串代码 #include <stdio.h> int main() {int i 0;scanf("%d", &i);printf("输入十以内的数字&#xff0c;从输入的数字开始一直数到十&#xff1a;");while (i<10){printf(…

php ext-sodium 拓展安装 linux+windows

php编译安装(linux)&#xff0c;可以参考&#xff1a;php编译安装 一、windows soduim源码包自带&#xff0c;直接修改php.ini&#xff0c;取消extensionsodium注释即可 二、linux 1.安装依赖 apt-get install libsodium-dev2.进入源码目录 这里写自己的源码目录 cd /us…

6种版本的并查集(java实现版)

目录 引入 并查集的具体讲解及代码实现 Quick Find Quick Union 基于size的优化 代码实现 基于rank的优化 代码实现 路径压缩 代码实现 更多关于路径压缩的并查集 引入 由孩子指向父亲的这种特殊的树结构可以很高效的处理连接问题&#xff0c;在一个复杂的图中&…