BFS(广度优先搜索)——搜索算法
BFS,也就是广度(宽度)优先搜索,二叉树的层序遍历就是一个BFS的过程。而前、中、后序遍历则是DFS(深度优先搜索)。从字面意思也很好理解,DFS就是一条路走到黑,BFS则是一层一层地展开。
关于二叉树的创建与遍历,大家可以参考下文:
二叉树创建和遍历_二叉树的建立与遍历-CSDN博客
下图分别是DFS和BFS的遍历顺序图解:
一、层序遍历
接下来我们直接来看题,从题中感受BFS的魅力。
N叉树与二叉树的区别无非就是二叉树最多只有两个子节点用left和right两个指针就够储存。而N叉树有N多个节点,需要一个指针数组来储存。
在用BFS解决问题时几乎都要借助队列结构,用队列的先进先出特性来储存上一层的数据。
首先把根节点放到队列里面,然后从队列里面取节点出来,把节点取出来后,通过它找到它的子节点并带入到队列里面。那么这个节点的使命就算完成了,需要把它踢出队列。循环往复直到最后队列为空,则完成层序遍历。
但对于这个题并不是简单的层序遍历就行,它还要把每一层划分出来。这个其实也很简单,只要记录每一层有几个节点(记为n个),然后一次性的遍历n个,并把这n个元素用数组储存起来。可以直接使用size()计算该层元素个数。
代码示例:
class Solution {
public:vector<vector<int>> levelOrder(Node* root){if(!root) return {};vector<vector<int>> ret;queue<Node*> qu;qu.push(root);while(!qu.empty()){vector<int> arr;int n=qu.size();//获取该层有一个元素while(n--)//取出该层的所以元素并把子节点带入{Node* rt=qu.front();qu.pop();arr.push_back(rt->val);for(int i=0;i<rt->children.size();i++)qu.push(rt->children[i]);}if(!arr.empty()) ret.push_back(arr);} return ret;}
};
二、最短路问题
例如我们要找到从起点(1)到终点(8)的最短路径。
最终找到最短路如下:
例题:
首先因为它是上下左右式的扩散,所以使用一个小技巧:向量坐标,
dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};
我们使用
for(int k=0;k<4;k++)
x1 = x+dx[k], y1 = y+dy[k];
就可以得到(x, y)的上下左右坐标的(x1, y1)。
它的扩展逻辑就和上文层序遍历中那一题差不多,但需要一个变量记录层数。在扩展过程中需要判断是否是目标值,还需要把扩展到的元素做标记。
代码示例:
class Solution {
public:int dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};int nearestExit(vector<vector<char>>& maze, vector<int>& entrance){int n = maze.size(),m = maze[0].size();vector<vector<bool>> hash(n,vector<bool>(m));//记录是否已经搜索过queue<pair<int,int>> qu;qu.push({entrance[0],entrance[1]});hash[entrance[0]][entrance[1]] = true;int ret = 0;//记录层数while(!qu.empty()){ret++;int sz = qu.size();while(sz--){auto [a,b] = qu.front();qu.pop();for(int k=0;k<4;k++){int x = a+dx[k],y = b+dy[k];if(x>=0&&x<n&&y>=0&&y<m&&!hash[x][y]&&maze[x][y]=='.'){if(x==0||x==n-1||y==0||y==m-1) return ret;hash[x][y] = true;qu.push({x,y});}}}}return -1;}
};
这个题我们可以做一个多趟的BFS,首先确定第一个起点和终点,进行BFS搜索并记录路径长度。
注意:由题可知没有两棵树的高度是相同的,也就是说树的高度和它的坐标是一一对应的。
具体操作如下:
把所有树的高度(>1的元素)都记录到一个数组中,然后对该数组进行排序。这样我们就知道搜索的先后顺序。
封装一个bfs函数,如pair<int,int> bfs(int x,int y,int target,vector<vector<int>>& forest),传入起点坐标与终点的值,它的作用是记录起点到终点的最短距离,然后返回终点的坐标。如果不能被搜索到返回{-1, -1}。
距离的计算我们可以使用一个全局变量在bfs中累加。
进行一次bfs后得到的返回值作为下一次搜索的起点下标,而终点值从刚才排序好的数组中取到。
最后,使用循环把数组中所有的值都搜索一遍。
class Solution {
public:int ret = 0,m = 0,n = 0;int dx[4] = {0,0,-1,1},dy[4]={-1,1,0,0};int cutOffTree(vector<vector<int>>& forest){m = forest.size(),n = forest[0].size();vector<int> arr;for(int i=0;i<m;i++)for(int j=0;j<n;j++)if(forest[i][j]>1) arr.push_back(forest[i][j]);sort(arr.begin(),arr.end());int x = 0,y = 0;for(int i=0;i<arr.size();i++){if(i==0&&arr[i]==forest[0][0]) continue;auto [a,b] = bfs(x,y,arr[i],forest);if(a==-1) return -1;x = a,y = b;}return ret;}pair<int,int> bfs(int x,int y,int target,vector<vector<int>>& forest){vector<vector<bool>> hash(m,vector<bool>(n));queue<pair<int,int>> qu;qu.push({x,y});hash[x][y] = true;while(!qu.empty()){ret++;int sz = qu.size();while(sz--){auto [a,b] = qu.front();qu.pop();for(int k=0;k<4;k++){int x1 = a+dx[k],y1 = b+dy[k];if(x1>=0&&x1<m&&y1>=0&&y1<n&&!hash[x1][y1]&&forest[x1][y1]!=0){if(forest[x1][y1]==target) return {x1,y1};hash[x1][y1]=true;qu.push({x1,y1});}}}}return {-1,-1};}
};
三、多源最短路问题
多源最短路它的特点就是可以选择多个起点,找出到达终点的最短路径。
其实它和单源最短路差别并不是很大,我们只需要把所有起点看作一个整体,也就是把它当作“超级源点”那么它就是一个单源最短路问题。
这个题很明显我们可以使用BFS解决,但是如果每个1的位置都用一次BFS搜索,未免也太麻烦,那么我们可以用多源最短路的思想,把所有0当作起点,然后去搜索1并填充最短路径。 那么为什么不用所有的1为起点去搜索0呢,因为我们需要填写的信息是1的位置,如果用1去搜索0的话,最后就不能找到原来那个1的位置。
代码示例:
class Solution {
public:int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};vector<vector<int>> updateMatrix(vector<vector<int>>& mat){int m=mat.size(),n=mat[0].size();vector<vector<int>> ret(m,vector<int>(n,-1));//充当了哈希表的功能queue<pair<int,int>> q;for(int i=0;i<m;i++)//把所有起点加入队列中{for(int j=0;j<n;j++){if(mat[i][j]==0){q.push({i,j});ret[i][j]=0;}}}int tmp = 0;while(!q.empty()){tmp++;int sz = q.size();while(sz--){auto [i,j]=q.front();q.pop();for(int k=0;k<4;k++){int x=dx[k]+i,y=dy[k]+j;if(x>=0&&x<m&&y>=0&&y<n&&ret[x][y]==-1){ret[x][y]=tmp;q.push({x,y});}}}}return ret;}
};
四、拓扑排序问题
在一个有向无环图中,要保证在 “被指向的节点” 出现之前,它的 “父节点” 要先出现。
通常用顶点来表示一个活动,用边的指向来表示活动之间的先后顺序。如:
如上,拓扑排序的结果可能有多种,只要合法就行。
排序方法:
- 1.记录每个顶点的入度边个数,和出度边的指向。
- 2.把所有入度边为0的节顶点push到队列中。
- 3.拿出队头元素加入到结果中。
- 4.把该元素指向的所有顶点入度边减1,并判断如果有顶点的入度边为0则push到队列。
- 循环执行3,4部直到队列为空,则完成排序。
210. 课程表 II - 力扣(LeetCode)
class Solution {
public:vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {vector<int> in(numCourses), ret;vector<vector<int>> out(numCourses);for(int i=0;i<prerequisites.size();i++){int a=prerequisites[i][0];int b=prerequisites[i][1];in[a]++;out[b].push_back(a);} queue<int> q;for(int i=0;i<numCourses;i++)if(in[i]==0) q.push(i);while(!q.empty()){int v = q.front();ret.push_back(v);q.pop();for(int i=0;i<out[v].size();i++)if(--in[out[v][i]]==0) q.push(out[v][i]);}if(ret.size()!=numCourses) return {};return ret;}
};
相关文章:

BFS(广度优先搜索)——搜索算法
BFS,也就是广度(宽度)优先搜索,二叉树的层序遍历就是一个BFS的过程。而前、中、后序遍历则是DFS(深度优先搜索)。从字面意思也很好理解,DFS就是一条路走到黑,BFS则是一层一层地展开。…...

JVM 四虚拟机栈
虚拟机栈出现的背景 由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的。优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要更多…...

【R语言】获取数据
R语言自带2种数据存储格式:*.RData和*.rds。 这两者的区别是:前者既可以存储数据,也可以存储当前工作空间中的所有变量,属于非标准化存储;后者仅用于存储单个R对象,且存储时可以创建标准化档案,…...

Java BIO详解
一、简介 1.1 BIO概述 BIO(Blocking I/O),即同步阻塞IO(传统IO)。 BIO 全称是 Blocking IO,同步阻塞式IO,是JDK1.4之前的传统IO模型,就是传统的 java.io 包下面的代码实现。 服务…...
统计满足条件的4位数(信息学奥赛一本通-1077)
【题目描述】 给定若干个四位数,求出其中满足以下条件的数的个数:个位数上的数字减去千位数上的数字,再减去百位数上的数字,再减去十位数上的数字的结果大于零。 【输入】 输入为两行,第一行为四位数的个数n࿰…...
北京门头沟区房屋轮廓shp的arcgis数据建筑物轮廓无偏移坐标测评
在IT行业中,地理信息系统(GIS)是用于处理、分析和展示地理空间数据的重要工具,而ArcGIS则是GIS领域中的一款知名软件。本文将详细解析标题和描述中提及的知识点,并结合“门头沟区建筑物数据”这一标签,深入…...
Spring 面试题【每日20道】【其三】
1、Spring 中的 Profile 注解的作用是什么? 中等 Profile 注解在Spring框架中用于根据不同的环境配置文件(profiles)来激活或忽略某些Bean的注册。它允许开发者定义逻辑以区分不同环境下的bean定义,例如开发、测试和生产环境。 …...

FFmpeg(7.1版本)在Ubuntu18.04上的编译
一、从官网上下载FFmpeg源码 官网地址:Download FFmpeg 点击Download Source Code 下载源码到本地电脑上 二、解压包 tar -xvf ffmpeg-7.1.tar.xz 三、配置configure 1.准备工作 安装编译支持的软件 ① sudo apt-get install nasm //常用的汇编器,用于编译某些需要汇编…...
Apache Hudi数据湖技术应用在网络打车系统中的系统架构设计、软硬件配置、软件技术栈、具体实现流程和关键代码
网络打车系统利用Hudi数据湖技术成功地解决了其大规模数据处理和分析的难题,提高了数据处理效率和准确性,为公司的业务发展提供了有力的支持。 Apache Hudi数据湖技术的一个典型应用案例是网络打车系统的数据处理场景,具体如下: 大…...

安全策略配置
需求: 1、VLAN 2属于办公区;VLAN 3属于生产区 2、办公区PC在工作日时间(周一至周五,早8到晚6)可以正常访问0A Server,其他时间不允许 3、办公区PC可以在任意时刻访问web server 4、生产区PC可以在任意时刻访问0A Server,但是不能访问Web serv…...
c++ stl 遍历算法和查找算法
概述: 算法主要由头文件<algorithm> <functional> <numeric> 提供 <algorithm> 是所有 STL 头文件中最大的一个,提供了超过 90 个支持各种各样算法的函数,包括排序、合并、搜索、去重、分解、遍历、数值交换、拷贝和…...

【Envi遥感图像处理】008:波段(批量)分离与波段合成
文章目录 一、波段分离提取1. 提取单个波段2. 批量提取单个波段二、波段合成相关阅读:【ArcGIS微课1000例】0058:波段合成(CompositeBands)工具的使用 一、波段分离提取 1. 提取单个波段...
线程创建与管理 - 创建线程、线程同步(C++)
前言 在现代软件开发中,线程的创建和管理是并发编程的核心内容之一。通过合理地创建和管理线程,可以有效提高程序的响应速度和资源利用率。本文将详细讲解如何在C中创建线程,并探讨几种常见的线程同步机制。我们假设读者具备一定的C基础&…...

【C语言篇】“三子棋”
一、游戏介绍 三子棋,英文名为 Tic - Tac - Toe,是一款简单而经典的棋类游戏。游戏在一个 33 的棋盘上进行,两名玩家轮流在棋盘的空位上放置自己的棋子(通常用 * 和 # 表示),率先在横、竖或斜方向上连成三个…...

安培定律应用于 BH 曲线上的工作点
在本篇博文中,我将展示如何应用安培定律来确定磁芯包裹的导体必须承载多少电流才能从 BH 值工作点获得 B 值,该工作点对应于磁芯材料中的最大 B 值。我在 BH 曲线上使用两个工作点,一个在线性区域,另一个在饱和区域。 安培定律 H…...

深度求索DeepSeek横空出世
真正的强者从来不是无所不能,而是尽我所能。多少有关输赢胜负的缠斗,都是直面本心的搏击。所有令人骄傲振奋的突破和成就,看似云淡风轻寥寥数语,背后都是数不尽的焚膏继晷、汗流浃背。每一次何去何从的困惑,都可能通向…...
【CSS】什么是响应式设计?响应式设计的基本原理,怎么做
在当今多设备、多屏幕尺寸的时代,网页设计面临着前所未有的挑战。传统的固定布局已无法满足用户在不同设备上浏览网页的需求,响应式设计(Responsive Web Design)应运而生,成为网页设计的趋势和标准。本文将深入探讨响应…...

后盾人JS--继承
继承是原型的继承 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </hea…...
提升开发效率:IDE使用技巧与插件推荐
在软件开发过程中,选择一个合适的集成开发环境(IDE)并掌握其使用技巧,可以显著提高开发效率。本文将分享一些常用的IDE使用技巧,并推荐几款实用的插件,帮助开发者更好地利用IDE进行开发。 一、IDE使用技巧…...
开源模型应用落地-DeepSeek-R1-Distill-Qwen-7B与vllm实现推理加速的正确姿势(一)
一、前言 在当今人工智能技术迅猛发展的时代,各类人工智能模型如雨后春笋般不断涌现,其性能的优劣直接影响着应用的广度与深度。从自然语言处理到计算机视觉,从智能安防到医疗诊断,AI 模型广泛应用于各个领域,人们对其准确性、稳定性和高效性的期望也与日俱增。 在此背景下…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
《Offer来了:Java面试核心知识点精讲》大纲
文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决
问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…...

算法—栈系列
一:删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...