宽度优先搜索算法(BFS)

宽度优先搜索算法(BFS)是什么?

宽度优先搜索算法(BFS)(也称为广度优先搜索)主要运用于树、图和矩阵(这三种可以都归类在图中),用于在图中从起始顶点开始逐层地向外探索,直到找到目标顶点为止。

在本篇文章中,我们主要讨论其在中的运用

树的宽度优先搜索

树的宽度优先搜索 即 树的层序遍历 :逐层访问树的节点,并按照层级顺序输出节点的值。从树的根节点开始,逐层向下遍历,先访问当前层的所有节点,然后再访问下一层的节点,依次类推直到遍历完整棵树

其过程如下图所示:

如何实现树的层序遍历呢?

我们在遍历每一层节点时,都是从左向右依次遍历的,即先遍历上一层节点中的第一个节点的孩子节点 ,即优先遍历前面的节点,此时,满足 “先进先出”,因此,我们可以使用队列来帮助我们完成层序遍历

具体步骤如下:

1. 先将根节点放入队列中

2. 从队列中出队一个节点,并将该节点的所有孩子节点(如果有)依次放入队列中

3. 继续取出节点,指导队列为空

4. 当队列为空时,遍历完成

接下来,我们通过一些练习来进一步体会和掌握BFS

相关练习

练习1:N叉树的层序遍历

题目链接:

429. N 叉树的层序遍历 - 力扣(LeetCode)

题目描述:

给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。

树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

示例 1:

输入:root = [1,null,3,2,4,null,5,6]
输出:[[1],[3,2,4],[5,6]]

示例 2:

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]]

提示:

  • 树的高度不会超过 1000
  • 树的节点总数在 [0, 10^4] 之间

思路分析:

 本题要求我们返回N叉树节点值的层序遍历,且以 List<List<Integer>>类型的结果返回,即每一层使用一个列表来存储本层的所有节点的值,然后将这些列表放到一个列表中返回

在这里,我们可以使用队列来帮助我们进行层序遍历,但在将节点出队时,也会将其孩子节点放入队列中,那么,我们如何区分每一层的节点呢?

 我们可以使用一个变量 count 在节点出队之前,记录队列当前节点个数(即这一层节点个数),然后再将这 count 个节点依次出队列,将其节点值放入列表中,同时将其孩子节点放入队列中

具体步骤:

1. 先判断树是否为空,不为空将根节点放入队列中

2. 记录当前队列中包含的节点个数count

3. 将count个节点依次出队列,将其节点值放入一个临时列表中,同时将其孩子节点放入队列中

4. 遍历完count个节点后,临时列表中就存放了这一层所有节点的值,然后再将临时列表放入结果列表中

5. 继续遍历,直到队列为空

6. 返回结果

代码实现:

class Solution {public List<List<Integer>> levelOrder(Node root) {List<List<Integer>> ret = new ArrayList<>();Node cur = root;Queue<Node> queue = new ArrayDeque<>();//先将根节点放入队列中if(cur == null) return ret;queue.add(cur);int count = 0;while (!queue.isEmpty()){//先记录当前队列中节点个数count = queue.size();List<Integer> tmp = new ArrayList<>();//使用临时表存储这一层节点的值for (int i = 0; i < count; i++) {cur = queue.poll();//将队头元素出队tmp.add(cur.val);for (Node child: cur.children) {//将队头元素的孩子节点放入队列中queue.add(child);}}ret.add(tmp);//将临时表放入ret中}return ret;}
}

练习2:二叉树的锯齿形层序遍历

题目链接:

103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode)

题目描述:

给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

示例 1:

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

示例 2:

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

示例 3:

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

提示:

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

思路分析:

 本题要求我们返回二叉树的锯齿形层序遍历,

什么是锯齿形层序遍历?

先从左向右,再从右向左地对每一层节点进行遍历

以示例1为例: 

当前层数为奇数时,从左向右遍历;当前层数为偶数时,从右向左遍历

因此,本题的解题思路与练习1类似,唯一不同的是:在偶数层时需要将所有节点的值进行逆序,我们可以使用一个int类型的变量(或boolean类型的变量)来标记这一层的节点是否需要逆序

代码实现:

class Solution {public List<List<Integer>> zigzagLevelOrder(TreeNode root) {List<List<Integer>> ret = new ArrayList<>();Queue<TreeNode> queue = new ArrayDeque<>();int flag = 1;//标识是否需要逆序TreeNode cur = root;//先将根节点放入队列中if(cur == null) return ret;queue.add(cur);int count = 0;while(!queue.isEmpty()){//先记录当前队列节点个数count = queue.size();//依次出队列List<Integer> tmp = new ArrayList<>();for(int i = 0; i < count; i++){cur = queue.poll();tmp.add(cur.val);//将其孩子节点入队列if(cur.left != null) queue.add(cur.left);if(cur.right != null) queue.add(cur.right);}//判断是否需要逆序if(flag == -1){Collections.reverse(tmp);}ret.add(tmp);flag = -flag;}return ret;}
}

练习3:在每个树行中找最大值

题目链接:

LCR 044. 在每个树行中找最大值 - 力扣(LeetCode)

题目描述:

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

示例1:

输入: root = [1,3,2,5,3,null,9]
输出: [1,3,9]
解释:1/ \3   2/ \   \  5   3   9 

示例2:

输入: root = [1,2,3]
输出: [1,3]
解释:1/ \2   3

示例3:

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

示例4:

输入: root = [1,null,2]
输出: [1,2]
解释:      1 \2     

示例5:

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

提示:

  • 二叉树的节点个数的范围是 [0,104]
  • -231 <= Node.val <= 231 - 1

思路分析:

题目要求我们找到二叉树中每一层中的最大值,因此,我们只需要进行层序遍历,并在每一层中寻找最大值即可

代码实现:

class Solution {public List<Integer> largestValues(TreeNode root) {List<Integer> ret = new ArrayList<>();TreeNode cur = root;Queue<TreeNode> queue = new ArrayDeque<>();//先将根节点放入if(cur == null) return ret;queue.add(cur);int count = 0;while(!queue.isEmpty()){//先计算队列中有多少个元素count = queue.size();//将元素依次出队列int max = Integer.MIN_VALUE;for(int i = 0; i < count; i++){cur = queue.poll();if(max < cur.val){//寻找这一层的最大值max = cur.val;}//将其孩子节点放入队列中if(cur.left != null) queue.add(cur.left);if(cur.right != null) queue.add(cur.right);}ret.add(max);//将这一层的最大值添加到ret中}return ret;}
}

练习4:二叉树的最大宽度

题目链接:

662. 二叉树最大宽度 - 力扣(LeetCode)

题目描述:

给你一棵二叉树的根节点 root ,返回树的 最大宽度 。

树的 最大宽度 是所有层中最大的 宽度 。

每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null 节点,这些 null 节点也计入长度。

题目数据保证答案将会在  32 位 带符号整数范围内。

示例 1:

输入:root = [1,3,2,5,3,null,9]
输出:4
解释:最大宽度出现在树的第 3 层,宽度为 4 (5,3,null,9) 。

示例 2:

输入:root = [1,3,2,5,null,null,9,6,null,7]
输出:7
解释:最大宽度出现在树的第 4 层,宽度为 7 (6,null,null,null,null,null,7) 。

示例 3:

输入:root = [1,3,2,5]
输出:2
解释:最大宽度出现在树的第 2 层,宽度为 2 (3,2) 。

提示:

  • 树中节点的数目范围是 [1, 3000]
  • -100 <= Node.val <= 100

思路分析:

 题目要求我们返回二叉树的最大宽度,需要注意的是:这里的宽度不是指这一层有多少个节点,而是指这一层最左端的非空节点left和最右端的非空节点right之间的长度,left和right之间为空或不存在的节点也需计入长度

我们以示例2为例:

left和right之间的节点及其延伸到这一层的null节点都要计入,因此,我们首先可以想到:可以添加这些空节点,即若当前节点的右孩子为空,则将null入队列;若当前节点为null,则将null null两个节点入队列,这样,我们就补齐了这一层两端点之间的节点,因此可以直接使用 count 变量记录这一层的宽度,但是,虽然树中节点的数目范围为 1 - 3000,但若出现极端情况,即:

此时,需要补充的空节点数量非常多,超出时间限制,因此,该方法不能解决本题

本层宽度 = 最左端的非空节点left和最右端的非空节点right之间的长度,因此,我们可以直接寻找最左端非空节点left的位置 和最右端非空节点right的位置,然后就可以直接求出这一层的宽度

如何找到最左端非空节点left的位置 和最右端非空节点right的位置?

我们对节点进行编号,从1开始(即根节点为1),这样当前节点cur的编号为index,则其左孩子为2*index,右孩子为2*index + 1,通过编号,我们就能很容易的找到每一个节点,此时,  每一层的宽度 = 最右侧非空节点right的编号 - 最左侧非空节点left的编号 + 1,在这里,我们使用 Pair(配对) 来关联当前节点和其编号

具体步骤:

1. 将根节点及其编号1放入队列中,此时最大宽度为1

2. 先记录当前队列中元素个数count

3. 将count个元素依次出队列,记录第一个节点的编号 和最后一个节点的编号,遍历过程中,将当前节点的孩子节点和编号放入队列中

4. 计算该层宽度 right - left + 1,并更新最大宽度

5. 继续遍历,直达队列为空

代码实现:

class Solution {public int widthOfBinaryTree(TreeNode root) {TreeNode cur = root;Queue<Pair<TreeNode, Integer>> queue = new ArrayDeque<>();queue.add(new Pair<TreeNode, Integer>(root, 1));//将根节点添加到队列中int ret = 1;//最大宽度int count = 0;while(!queue.isEmpty()){count = queue.size();int left = 0, right = 0;//记录最左端和最右端非空节点的编号for(int i = 0; i < count; i++){Pair<TreeNode, Integer> pair = queue.poll();int index = pair.getValue();if(i == 0) left = index;//第一个非空节点if(i == count - 1) right = index;//最后一个非空节点cur = pair.getKey();if(cur.left != null) queue.add(new Pair<TreeNode, Integer>(cur.left, index*2));if(cur.right != null) queue.add(new Pair<TreeNode, Integer>(cur.right, index*2 + 1));}ret = Math.max(ret, right - left + 1);//更新最大宽度}return ret;}
}

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

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

相关文章

指针--2

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言1.指针运算1.1.指针-整数1.2.指针-指针1.3.指针的关系运算 2.野指针2.1 野指针成因2.2 如何规避野指针 3.assert 断言4.指针的使用和传址调用4.1 strlen的模拟实…

【Tauri】(4):整合Tauri和actix-web做本地大模型应用开发,可以实现session 登陆接口,完成页面展示,进入聊天界面

1&#xff0c;视频地址 https://www.bilibili.com/video/BV1GJ4m1Y7Aj/ 【Tauri】&#xff08;4&#xff09;&#xff1a;整合Tauri和actix-web做本地大模型应用开发&#xff0c;可以实现session 登陆接口&#xff0c;完成页面展示&#xff0c;进入聊天界面 使用国内代理进行加…

6-DOF GraspNet: Variational Grasp Generation for Object Manipulation

总结&#xff1a; 使用变分自动编码器(VAE)对抓取进行采样&#xff0c;并使用基于点网的抓取评估器模型对采样的抓取进行评估和细化 摘要&#xff1a; 我们将抓取生成问题表述为 使用变分自编码器对一组抓取进行采样&#xff0c;并使用抓取评 估器模型对采样的抓取进行评估和…

备考2024年小学生古诗文大会:历年真题15题练习和独家解析

如何提高小学生古诗词的知识&#xff1f;如何激发小学生古诗词的学习兴趣&#xff1f;如何提高小学古诗词的学习成绩&#xff1f;如何备考2024年小学生古诗文大会&#xff1f;...如果你也在关心和这些问题&#xff0c;我的建议是参加每年一度的小学生古诗词大会&#xff08;免费…

亚马逊跨境电商名词解释

亚马逊界面名词解释 最常用的名词解释总结&#xff1a; ASIN&#xff1a;亚马逊标准标识号,也就是每个商品的编码标识,每个商品的都不同&#xff0c;可以把它当成该商品的“身份证号”。由亚马逊随机生成的字母数字组合。 SKU&#xff1a;库存进出计量单位。 Listing&#xf…

太强了!最全的大模型检索增强生成(RAG)技术概览!

本文是对检索增强生成&#xff08;Retrieval Augmented Generation, RAG&#xff09;技术和算法的全面研究&#xff0c;对各种方法进行了系统性的梳理。文章中还包含了我知识库中提到的各种实现和研究的链接集合。 鉴于本文的目标是对现有的RAG算法和技术进行概览和解释&#…

django学习记录07——订单案例(复选框+ajax请求)

1.订单的数据表 1.1 数据表结构 1.2 数据表的创建 models.py class Order(models.Model):"""订单号"""oid models.CharField(max_length64, verbose_name"订单号")title models.CharField(max_length64, verbose_name"名称&…

做跨境电商,选哪个浏览器好?跨境电商浏览器推荐

在我们的日常生活中&#xff0c;有很多浏览器可供选择&#xff0c;比如百度浏览器、谷歌浏览器和360、火狐等等。但是在跨境电商行业中&#xff0c;是否有特别适合我们卖家使用的浏览器呢&#xff1f;所谓跨境电商浏览器&#xff0c;就是为跨境电商用户设计的浏览器&#xff0c…

Unity 采用自定义通道ShaderGraph实现FullScreen的窗户雨滴效果

效果如下 ShaderGraph实现 N21 随机化 DragLayer分层 将DragLayer分成四层&#xff0c;分别调整每层的缩放和大小 Shader实现的链接&#xff08;Unity 雨水滴到屏幕效果&#xff09; 我也是参考这个实现Shader Graph

微信小程序-侧滑删除

简介 movable-view和movable-area是可移动的视图容器&#xff0c;在页面中可以拖拽滑动。 本篇文章将会通过该容器实现一个常用的拖拽按钮功能。 使用效果 代码实现 side-view.wtml 布局见下面代码&#xff0c;left view为内容区域&#xff0c;right view为操作按钮&a…

初探深度学习-手写字体识别

前言 手写数字的神经网络识别通常指的是通过训练有素的神经网络模型来识别和分类手写数字图像的任务。这种类型的任务是机器学习和计算机视觉领域的一个经典问题&#xff0c;经常作为入门级的图像识别问题来展示和测试各种机器学习算法的能力。在实际应用中&#xff0c;手写数…

mac电脑总卡蓝屏是怎么回事,苹果电脑老卡蓝屏怎么办

电脑老卡蓝屏是比较常见的电脑故障之一&#xff0c;导致这一问题的出现很可能是电脑本身的硬件&#xff0c;或电脑上的驱动安装错误&#xff0c;没法运行&#xff0c;当然也不排除其他的一些因素。虽说电脑蓝屏是电脑几乎都会出现的小毛病&#xff0c;不足以致命&#xff0c;但…

基于决策树实现葡萄酒分类

基于决策树实现葡萄酒分类 将葡萄酒数据集拆分成训练集和测试集&#xff0c;搭建tree_1和tree_2两个决策树模型&#xff0c;tree_1使用信息增益作为特征选择指标&#xff0c;B树使用基尼指数作为特征选择指标&#xff0c;各自对训练集进行训练&#xff0c;然后分别对训练集和测…

图论练习6

[NOIP2013]车站分级 Here 解题思路 由于起始点之间所选的站号&#xff0c;相互之间一定满足那么对于起始点间未选择的站号&#xff0c;一定满足选择的站号考虑用边来维护信息&#xff0c;表示的级别大于按题意&#xff0c;则车站会被分为几个联通块&#xff0c;且保证块内无环…

So you think you understand IP fragmentation?

文章目录 前言一、Why care?二、Prevention三、Well-understood?四、Introducing fragquiz五、A novel (?) algorithm六、Reader challenge七、traceroute八、ICMP参考资料 前言 本文来自&#xff1a;https://lwn.net/Articles/960913/ February 7, 2024This article was …

【Python】成功解决ModuleNotFoundError: No module named ‘seaborn’

【Python】成功解决ModuleNotFoundError: No module named ‘seaborn’ &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; …

高分辨率全球海洋温度和盐度再分析数据Global Ocean Physics Reanalysis(0.083°),并利用matlab读取绘图

1.引言 在研究全球海平面变化的问题中&#xff0c;卫星测高获得总的海平面变化&#xff0c;而海平面变化包含质量变化和比容变化。因此测高数据和海洋物理分析数据对于海平面研究至关重要。 测高数据下载网址&#xff1a; Global Ocean Gridded L 4 Sea Surface Heights And …

动态规划课堂4-----子数组系列

目录 引入&#xff1a; 例题1&#xff1a;最大子数组和 例题2&#xff1a;环形子数组的最大和 例题3&#xff1a;乘积最大子数组 例题4&#xff1a;乘积为正数的最长子数组 总结&#xff1a; 结语&#xff1a; 引入&#xff1a; 在动态规划&#xff08;DP&#xff09;子…

农场管理小程序|基于微信小程序的农场管理系统设计与实现(源码+数据库+文档)

农场管理小程序目录 目录 基于微信小程序的农场管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、用户信息管理 2、农场信息管理 3、公告信息管理 4、论坛信息管理 四、数据库设计 五、核心代码 七、最新计算机毕设选题推荐 八、源码获取&#x…

【工具使用-VScode】VScode如何设置空格和tab键显示

一&#xff0c;简介 在提交代码的时候&#xff0c;行末尾的tab和空格不符合规范&#xff0c;但是如果在vscode中不显示tab和空格的话&#xff0c;不能及时的查看到并改正&#xff0c;导致提交代码之后还需要再次进行修改&#xff0c;效率比较低。 代码编辑界面如图所示&#…