一文弄懂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经典问题,详细介绍和解题思路:
- 二叉树的层次遍历
在这个问题中,我们需要通过 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’(陆地)和 ‘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;
}
- 打开密码锁的最少步数
给你一个初始为 ‘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;
}
- 图中两点间最短路径长度
给定一个无向图,求从起点 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];
}
- 找到最近的医院
给定一个二维的 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;
}
- 最小基因变异
给定两个基因序列 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,全名为广度优先搜索(Breadth-First Search),是一种用于图或树的遍历或搜索的算法。它的主要思想是由节点自身开始向它的邻居节点新进展开搜索,因此也常被形象地称为“层序遍历”。 BFS 基本思想 BFS 工作原理是,从开始节点开…...

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

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

第十五届蓝桥杯模拟赛(第二期)
大家好,我是晴天学长,本次分享,制作不易,本次题解只用于学习用途,如果有考试需要的小伙伴请考完试再来看题解进行学习,需要的小伙伴可以点赞关注评论一波哦!后续会继续更新第三期的。Ǵ…...

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

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

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

会泽一村民上山放羊吸烟引发森林火灾,AI科技急需关注
2023年4月,会泽县古城街道厂沟村委会望香台山林中发生了一场由疏忽引发的森林火灾。张某某在放羊时未完全熄灭烟头,导致7.33公顷的林地和草地被焚毁,直接经济损失高达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颜色矩
颜色矩(Color Moments)是一种常用的图像特征描述方法,用于表示图像中颜色的分布和统计特征。它是基于图像的颜色直方图而计算得到的。 颜色矩通常包括三个维度:平均值、方差和偏度。具体来说: 平均值(Mean…...

〖大前端 - 基础入门三大核心之JS篇㊹〗- DOM事件委托
说明:该文属于 大前端全栈架构白宝书专栏,目前阶段免费,如需要项目实战或者是体系化资源,文末名片加V!作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 从事过全栈研发、产品经理等工作…...

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

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

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 客户端管理工具,支持 Git 项目的创建、克隆、提交、push、pull 和合并等操作。它拥有一个精美简洁的界面,大大简化了开发者与代码库之间的 Git 操作方式,这对于不熟悉 …...

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

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

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

【每日一题】1423. 可获得的最大点数-2023.12.3
题目: 1423. 可获得的最大点数 几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。 每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。 你的点数就是你拿到手中的所有…...

VSCode修改C++版本
新下载了一下VSCode,想使用C17的特性std::optional,但是显示有错误,想想可能是C 版本的问题,查了一下资料,按下面的博客操作,果然解决了。 vscode设置c 版本...

31-WEB漏洞-文件操作之文件包含漏洞全解
31-WEB漏洞-文件操作之文件包含漏洞全解 一、本地包含1.1、无限制包含漏洞文件1.2、有限制包含漏洞文件1.2.1、绕过方法1.2.1.1、%00截断1.2.1.2、长度截断 二、远程包含2.1、无限制包含漏洞文件2.2、有限制包含漏洞文件 三、各种协议流提交流3.1、各协议的利用条件和方法3.1.1…...

预约系统源码解析:打造智能定制化预约服务的技术奇迹
在当今数字化时代,预约系统的重要性日益凸显,而预约系统源码的开放将为各行业带来更加灵活、智能的预约解决方案。本文将深入探讨预约系统源码的技术内幕,为开发者提供实用的代码示例,助力打造智能定制化的预约服务。 技术栈概览…...

关于Maxscript你了解多少?
MAXScript是Autodesk 3dMax的内置脚本语言。MAXScript为3dMax用户提供了以下功能: 编写程序使用的大部分方面的脚本,如建模、动画、材质、渲染等。 通过命令行侦听器窗口以交互方式控制程序。 在自定义实用工具面板卷展栏或无模式窗口中打包脚本&…...

Xshell全局去除提示音
使用Xshell的时候经常会按TAB或者一些操作指令的时候的时候听到提示音,非常的烦 通常来说在Xshell中可以单独修改每一个会话的属性,将提示音关闭,但是新增的会话依然带有提示音,还得一个个的关闭,非常麻烦,…...

JAVA代码优化:Spring中redis的工具类
基于Spring框架和Redis的缓存工具类。该类提供了一系列方法用于操作Redis缓存,包括设置缓存对象、设置缓存超时时间、获取缓存对象、删除对象、缓存List、Set、Map等操作。通过这些方法可以方便地对Redis进行数据缓存和读取操作。同时,该类使用了Spring的…...

MathType 7.5.2中文版软件使用期到了怎么办?
MathType 7.5.2中文版作为一款专业的公式编辑器,MathType受到很多人的青睐,它可以将编辑好的公式保存成多种图片格式或透明图片模式,可以很方便的添加或移除符号、表达式等模板(只需要简单地用鼠标拖进拖出即可),也可以…...

DOM 事件的注册和移除
前端面试大全DOM 事件的注册和移除 🌟经典真题 🌟DOM 注册事件 HTML 元素中注册事件 DOM0 级方式注册事件 DOM2 级方式注册事件 🌟DOM 移除事件 🌟真题解答 🌟总结 🌟经典真题 总结一下 DOM 中如何…...

挖漏洞之SQL注入
(一)漏洞原理 1、 漏洞原理 SQL注入的原理是,是应用系统没有对传递的参数进行过滤,让参数直接拼接到SQL语句中,攻击通过对参数进行篡改,当参数传递到数据库中,逻辑上就会发生变化,就…...