当前位置: 首页 > news >正文

一文弄懂BFS【广度优先搜索(Breadth-First Search)】

在这里插入图片描述

BFS,全名为广度优先搜索(Breadth-First Search),是一种用于图或树的遍历或搜索的算法。它的主要思想是由节点自身开始向它的邻居节点新进展开搜索,因此也常被形象地称为“层序遍历”。

BFS 基本思想

BFS 工作原理是,从开始节点开始,在访问节点的邻居节点之前,我们先访问其它节点。换句话说,我们旧基于当前层次来遍历节点,然后移至下一层再遍历节点。BFS 是以一种队列(Queue)结构的方式运行的,首先我们有一个包含开始节点的队列,然后:

- 我们从队列的前端取出一个节点
- 为了防止回溯和重复访问,我们会标记取出的节点为已访问
- 针对取出的节点,把尚未访问过的邻居节点全部加入队列
- 我们重复以上步骤,直至队列为空

通过以上步骤,你将会发现,你在访问节点的时候,首先访问的是距离开始节点最近的节点(层次最低的节点),然后层次逐渐提升,这就是 BFS 的特性。

BFS 伪代码模板

BFS 主要应用于树和图结构的遍历,因此伪代码也大致分为对应的两类(以下都是基于未标记图进行的操作):

  • 树的广度优先搜索
function BFS(root) {initialize queue;queue.push(root);while(!queue.empty()) {node = queue.front();queue.pop();process(node); //处理节点nodes = generate_related_nodes(node); //获取与节点相关的未访问过的子节点queue.push(nodes);}
}
  • 图的广度优先搜索
function BFS(graph, start) {initialize queue and visited set;queue.push(start);visited.insert(start);while(!queue.empty()) {node = queue.front();queue.pop();process(node); //处理节点nodes = generate_related_nodes(node); //获取与节点相关的邻居节点for(node in nodes) {if(node not in visited) { //如果邻居节点尚未访问过queue.push(node);visited.add(node);}}}
}

接下来举出六个BFS经典问题,详细介绍和解题思路:

  1. 二叉树的层次遍历

在这个问题中,我们需要通过 BFS 遍历二叉树的每一层,以二维数组的形式返回结果。

vector<vector<int>> levelOrder(TreeNode* root) {if (!root) return {};vector<vector<int>> result;queue<TreeNode*> q;q.push(root);while (!q.empty()) {vector<int> one_level;for (int i = q.size(); i > 0; i--) {TreeNode* node = q.front();q.pop();one_level.push_back(node->val);if (node->left) q.push(node->left);if (node->right) q.push(node->right);}result.push_back(one_level);}return result;
}
  1. 岛屿的个数

给定一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,计算岛屿的数量。

解题思路主要是遍历二维数组,当遇到 ‘1’ 时,通过 BFS 搜索并 ‘感染’ 周围的 ‘1’,最后计算 ‘1’ 的个数。

int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};void bfs(vector<vector<char>>& grid, int x, int y, int row, int col) {queue<pair<int, int>> q;q.push({x, y});grid[x][y] = '0';  // 把 '1' 感染为 '0'while (!q.empty()) {auto [r, c] = q.front();q.pop();for (int i = 0; i < 4; ++i) {int nx = r + dx[i], ny = c + dy[i];if (nx >= 0 && nx < row && ny >= 0 && ny < col && grid[nx][ny] == '1') {q.push({nx, ny});grid[nx][ny] = '0';}}}
}int numIslands(vector<vector<char>>& grid) {int row = grid.size();if (row == 0) {return 0;}int col = grid[0].size();int res = 0;for (int i = 0; i < row; ++i) {for (int j = 0; j < col; ++j) {if (grid[i][j] == '1') {bfs(grid, i, j, row, col);++res;  // 计算岛屿数量}}}return res;
}
  1. 打开密码锁的最少步数

给你一个初始为 ‘0000’ 的四位密码,你可以每次对密码的任意一位做上下旋转:旋转一次可以将该位的数字增加 1 或减少 1 。求出最少的旋转次数,使得密码等于 target 。

int openLock(vector<string>& deadends, string target) {unordered_set<string> dead(deadends.begin(), deadends.end());if (dead.count("0000")) return -1;if (target == "0000") return 0;unordered_map<string, int> dist{{"0000", 0}};queue<string> q;q.push("0000");while (!q.empty()) {string t = q.front(); q.pop();for (int i = 0; i < 4; i++) {for (int j = -1; j <= 1; j += 2) {string str = t;str[i] = (str[i] - '0' + j + 10) % 10 + '0';if (str == target) return dist[t] + 1;if (!dead.count(str) && !dist.count(str)) {dist[str] = dist[t] + 1;q.push(str);}}}}return -1;
}
  1. 图中两点间最短路径长度

给定一个无向图,求从起点 s 到终点 t,最短路径长度是多少。

vector<unordered_set<int>> g; // 图
unordered_map<int, int> dist; // 从起点到每个点的距离int bfs(int s, int t) {queue<int> q;q.push(s);dist[s] = 0;while (!q.empty()) {int x = q.front(); q.pop();for (int y : g[x]) {if (!dist.count(y)) {dist[y] = dist[x] + 1;q.push(y);}}}return dist[t];
}
  1. 找到最近的医院

给定一个二维的 0-1 矩阵,1 表示医院,0 表示型房屋。求每个房屋距离最近医院的距离。

vector<vector<int>> dirs = {{-1,0}, {1,0}, {0,-1}, {0,1}};vector<vector<int>> findNearestHospital(vector<vector<int>>& grid) {int m = grid.size(), n = grid[0].size();vector<vector<int>> dist(m, vector<int>(n, INT_MAX));queue<pair<int, int>> q;// BFS 队列// 先把所有的医院节点放进队列,然后开始 BFSfor(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {if(grid[i][j] == 1) {dist[i][j] = 0;q.push({i, j});}}}while(!q.empty()) {auto cur = q.front(); q.pop();for(auto dir : dirs) {int nx = cur.first + dir[0], ny = cur.second + dir[1];if(nx >= 0 && ny >= 0 && nx < m && ny < n) {if(dist[nx][ny] > dist[cur.first][cur.second] + 1) {dist[nx][ny] = dist[cur.first][cur.second] + 1;q.push({nx, ny});}}}}return dist;
}
  1. 最小基因变异

给定两个基因序列 start 和 end,一个基因库表 bank,求出把 start 变到 end 所需要的最小变异次数。一次基因变化代表改变一个字母。

int minMutation(string start, string end, vector<string>& bank) {unordered_set<string> dict(bank.begin(), bank.end());if (!dict.count(end)) return -1;unordered_map<string, int> dist{{start, 0}};queue<string> q;q.push(start);while (!q.empty()) {string gene = q.front(); q.pop();if (gene == end) return dist[gene];for (int i = 0; i < gene.size(); i++) {string newGene = gene;for (char c : "ACGT") {newGene[i] = c;if (dict.count(newGene) && !dist.count(newGene)) {dist[newGene] = dist[gene] + 1;q.push(newGene);}}}}return -1;
}

如果你想更深入地了解人工智能的其他方面,比如机器学习、深度学习、自然语言处理等等,也可以点击这个链接,我按照如下图所示的学习路线为大家整理了100多G的学习资源,基本涵盖了人工智能学习的所有内容,包括了目前人工智能领域最新顶会论文合集和丰富详细的项目实战资料,可以帮助你入门和进阶。

链接: 人工智能交流群【最新顶会与项目实战】(点击跳转)

在这里插入图片描述

相关文章:

一文弄懂BFS【广度优先搜索(Breadth-First Search)】

BFS&#xff0c;全名为广度优先搜索(Breadth-First Search)&#xff0c;是一种用于图或树的遍历或搜索的算法。它的主要思想是由节点自身开始向它的邻居节点新进展开搜索&#xff0c;因此也常被形象地称为“层序遍历”。 BFS 基本思想 BFS 工作原理是&#xff0c;从开始节点开…...

深度学习记录--logistic回归函数的计算图

计算图用于logistic回归函数 先回顾一下单一样本的logistic回归损失函数的公式&#xff0c;公式如下&#xff1a; 将logistic函数用计算图表示出来(以两个基础量为例)&#xff0c;计算图如下&#xff1a; 前向传播已经完成&#xff0c;接下来完成后向传播 运用链式法则依次求…...

Java基本数据类型详解

✨个人主页&#xff1a;全栈程序猿的CSDN博客 &#x1f4a8;系列专栏&#xff1a;Java从入门到精通 ✌座右铭&#xff1a;编码如诗&#xff0c;Bug似流星&#xff0c;持续追求优雅的代码&#xff0c;解决问题如同星辰般自如 Java是一种强类型语言&#xff0c;数据类型在程序中起…...

第十五届蓝桥杯模拟赛(第二期)

大家好&#xff0c;我是晴天学长&#xff0c;本次分享&#xff0c;制作不易&#xff0c;本次题解只用于学习用途&#xff0c;如果有考试需要的小伙伴请考完试再来看题解进行学习&#xff0c;需要的小伙伴可以点赞关注评论一波哦&#xff01;后续会继续更新第三期的。&#x1f4…...

命令模式-C++实现

命令模式是一种行为型设计模式&#xff0c;它将请求封装成一个对象&#xff0c;从而能使你可以用不同的请求对客户端进行参数化。该模式允许请求的发送者和接收者进行解耦&#xff0c;发送者不需要知道接收者的信息&#xff0c;只需要通过命令对象来与它进行交互。 命令模式有…...

3dMax拼图生成工具Puzzle2D使用教程

Puzzle2D for 3dsMax拼图生成工具使用教程 Puzzle2D简介&#xff1a; 2D拼图随机生成器&#xff08;英文&#xff1a;Puzzle2D&#xff09; &#xff0c;是一款由#沐风课堂#用MAXScript脚本语言开发的3dsMax建模小工具&#xff0c;可以随机创建2D可编辑样条线拼图图形。可批量…...

git报错invalid object xxx和unable to read tree xxxxxx

电脑出问题了&#xff0c;导致git仓库像是被损坏了一样&#xff0c;执行git status就会报错unable to read ree&#xff0c;无法正常提交代码至仓库&#xff0c;原因是本地代码仓库.git文件损坏了&#xff0c;无法找到正确的提交历史和路径。 找到了一个解决办法&#xff1a; …...

会泽一村民上山放羊吸烟引发森林火灾,AI科技急需关注

2023年4月&#xff0c;会泽县古城街道厂沟村委会望香台山林中发生了一场由疏忽引发的森林火灾。张某某在放羊时未完全熄灭烟头&#xff0c;导致7.33公顷的林地和草地被焚毁&#xff0c;直接经济损失高达29.097万元。这一事件再次凸显了日常生活中的安全隐患。 在这一背景下&…...

docker-compose部署zabbix+grafana

1.引言 1.1目的 zabbixgrafana实现图形化监控 2.部署环境 服务器ip服务版本192.168.5.137zabbix-server6.0.21192.168.5.137grafana10.2.2192.168.5.152zabbix-client6.0.21 3.部署zabbix-server 3.1 创建zabbix目录 mkdir zabbix3.2 编写docker-compose文件 cd zabbix…...

ios 逆向分分析,某业帮逆向算法(二)

接上讲 上次hook 发现自己的数据有点问题。才发现是自己的编辑器识别出问题了。 上篇sub_1029B6898函数hook数据如下: [iOS Device::作业帮 ]-> arg2: 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 00000000 37 32 65 64 38 31 32 38…...

openCv颜色矩

颜色矩&#xff08;Color Moments&#xff09;是一种常用的图像特征描述方法&#xff0c;用于表示图像中颜色的分布和统计特征。它是基于图像的颜色直方图而计算得到的。 颜色矩通常包括三个维度&#xff1a;平均值、方差和偏度。具体来说&#xff1a; 平均值&#xff08;Mean…...

〖大前端 - 基础入门三大核心之JS篇㊹〗- DOM事件委托

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费&#xff0c;如需要项目实战或者是体系化资源&#xff0c;文末名片加V&#xff01;作者&#xff1a;不渴望力量的哈士奇(哈哥)&#xff0c;十余年工作经验, 从事过全栈研发、产品经理等工作&#xf…...

正是阶段高等数学复习--函数极限的计算

之前在预备阶段中函数极限的解决方式分三步&#xff0c;第一步观察形式并确定用什么方式来解决&#xff0c;第二步化简&#xff0c;化简方式一共有7种&#xff0c;分别是最重要的三种&#xff08;等价替换、拆分极限存在的项、计算非零因子&#xff09;以及次重要的4种&#xf…...

Linux-usb触摸板去除鼠标箭头

usb触摸板会同时加载hid-generic.c和hid-multitouch.c驱动 [ 213.602561] usb 4-1: new full-speed USB device number 2 using ohci-platform [ 213.834953] usb 4-1: New USB device found, idVendor6615, idProduct108c, bcdDevice 1.30 [ 213.835048] usb 4-1: New USB…...

【微信小程序】英文字母不换行问题 flex布局字符超出宽度折行问题:设置了word-break: break-all;和flex: 1;冲突flex不生效问题

flex布局中英文字符超出宽度不会自动折行的问题&#xff0c;但是设置了word-break: break-all&#xff1b;前面设置的flex: 1&#xff1b;就不生效了 1.英文字母不换行问题 .view_text {word-break: break-all; }如果使用flex仅仅设置word-break: break-all&#xff1b;是会影…...

python--自动化办公(Word)

python自动化办公之—Word python-docx库 1、安装python-docx库 pip install python-docx2、基本语法 1、打开文档 document Document() 2、加入标题 document.add_heading(总标题,0) document.add_heading(⼀级标题,1) document.add_heading(⼆级标题,2) 3、添加文本 para…...

sourceTree的下载和安装

sourceTree的下载和安装 一、概述 SourceTree 是一款免费的 Git 和 Hg 客户端管理工具&#xff0c;支持 Git 项目的创建、克隆、提交、push、pull 和合并等操作。它拥有一个精美简洁的界面&#xff0c;大大简化了开发者与代码库之间的 Git 操作方式&#xff0c;这对于不熟悉 …...

解决:ModuleNotFoundError: No module named ‘PyQt5‘

解决&#xff1a;ModuleNotFoundError: No module named ‘PyQt5’ 文章目录 解决&#xff1a;ModuleNotFoundError: No module named PyQt5背景报错问题报错翻译报错位置代码报错原因解决方法安装PyQt5在PyCharm中配置PyQt5对于新项目对于已有项目 今天的分享就到此结束了 背景…...

极客时间 - 如何成为学习高手【文章笔记 + 思考总结】

如何成为学习高手【文章笔记 思考总结】 高度自律 高度自律 5分钟起步法。 稍微走在计划前面。 替代拖延法。 自律&#xff1a;从不自律的念头中&#xff0c;约束自己。有变弱倾向时进行对抗。 在一种痛苦和另一种痛苦之间做选择&#xff0c;选择那个有意义的痛苦。 在某些固…...

前端笔记(二):CSS 选择器与特性

CSS&#xff08;层叠样式表&#xff09;是一种样式表语言&#xff0c;用于描述HTML或XML文档的呈现方式。它定义了如何在屏幕、纸张或其他媒体上显示文档的样式、布局和外观。 里面的代码由 选择器 { } 组成 体验 CSS CSS 可以让我们界面变得更加美观&#xff0c;这是 CSS 的…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...