【刷题22】BFS解决最短路问题

目录

  • 一、边权为1的最短路问题
  • 二、迷宫中离入口最近的出口
  • 三、最小基因变化
  • 四、单词接龙
  • 五、为高尔夫比赛砍树

一、边权为1的最短路问题

在这里插入图片描述
如图:从A到I,怎样走路径最短

  • 一个队列+一个哈希表
  • 队列:一层一层递进,直到目的地为止
  • 哈希表:记录当前位置是否经过,经过的就不用再进队列
  • 为什么可以使用BFS?因为每条边的长度为1,同样的速率走,走相同的步频,谁先到目的地,谁的路径就是最短的

二、迷宫中离入口最近的出口

题目:
在这里插入图片描述
思路:BFS+哈希表 找最短路径

  • 能到边界,返回ret,ret是层数
  • 不能到边界,队列层序结束,返回-1
  • 必须是某个位置的上下左右为边界才符合条件,即使刚开始就在边界也不行,也必须要移动,移动到另一个边界上才算;否则队列循环结束也是返回-1,参考示例2和示例3

代码:

class Solution {
public:int bx[4] = {-1,1,0,0};int by[4] = {0,0,-1,1};bool hash[100][100] = {false};int nearestExit(vector<vector<char>>& maze, vector<int>& entrance) {int n = maze.size();int m = maze[0].size();int ret = 0;queue<pair<int, int>> q;q.push({entrance[0], entrance[1]});while(!q.empty()){int k = q.size();ret++;// 一层的个数while(k--){int x1 = q.front().first;int y1 = q.front().second;// 防止重复if(hash[x1][y1]){q.pop();continue;}for(int i=0; i<4; i++){int x2 = x1+bx[i];int y2 = y1+by[i];if(x2>=0&&x2<n&&y2>=0&&y2<m&&maze[x2][y2]=='.'&&!hash[x2][y2]){if(x2==0 || x2==n-1 || y2==0 || y2==m-1){return ret;}q.push({x2, y2});}}// 标记经过的位置 更新队列hash[x1][y1] = true;q.pop();}}return -1;}
};

三、最小基因变化

题目:
在这里插入图片描述
题目理解:

  • 一次变化相当于步数,所以可以用BFS
  • 最终要变化成的基因序列必须是基因库中存在的,否则返回-1
  • 每一次的变化,也必须是在基因库中存在的,否则返回-1

思路:BFS+哈希表

  • 两个哈希表,一个标记基因库中有的基因序列,后续要使用(判断每次变化是否在基因库中);另一个标记是否已经出现过,防止重复
  • start字符串与end字符串相同,直接返回0
  • end字符串不在基因库中,直接返回-1
  • BFS:一个队列,层序遍历,一层就是一次变化
  • 基因序列如何变化?题目是字符串有8个字符,所以每个位置的字符变化一次,变化的字符有4个:ACGT
  • 只要在基因库中存在并且没有出现过,就入队列,如果该字符串与end字符串相同,就直接返回ret
  • 细节:变化前(内循环外面),先用一个临时字符串代替,这样保证只修改了一次;否则变化到后面,前面的也都变化了,就不止修改了一次
  • 队列层序完,没有end字符串等于tmp(变化的字符串),就说明start字符串变化不到end字符串,最终返回-1

在这里插入图片描述
代码:

class Solution {
public:int minMutation(string startGene, string endGene, vector<string>& bank) {unordered_map<string, int> hash; // 标记基因库中出现过的for(auto &e : bank) hash[e]++;unordered_map<string, int> vis; // 标记每次变化是否出现过 防止重复// 如果刚开始就相同if(startGene == endGene) return 0;// endGene不在基因库中if(hash[endGene] == 0) return -1;// 变化的字符string change = "ACGT";queue<string> q;int ret = 0; // 层数就是变化次数q.push(startGene);while(!q.empty()){int k = q.size();ret++;while(k--){string t = q.front();// 获取队列头vis[t]++;// 标记已经出现q.pop();// 删除for(int i=0; i<8; i++){string tmp = t;// 临时的,保证只修改一次for(int j=0; j<4; j++){tmp[i] = change[j];// 对应位置修改// 在基因库中存在并且还没出现过if(hash[tmp] > 0 && vis[tmp] == 0){q.push(tmp);// 等于最终的字符串 返回if(tmp == endGene){return ret;}}}}}}return -1;}
};

四、单词接龙

题目:
在这里插入图片描述

思路:BFS+哈希表

  • 本题与上题思路和过程几乎相同,字符=》字符串。以下是不同的地方要注意:
  • 都是一次改变,改变的是字符串中的一个字符,上题是ACGT,本题是wordList中出现的单词的所有字符,记得要去重。
  • 接下来是用队列完成层序遍历,与上题几乎一样,不同点:取队头元素时,要判断它是否出现过,出现过了就删除队头元素,然后continue(注意:其实加这个是为了避免重复计算,本题如果少了这个条件会超时;上题没有加这个条件并没有超时);因为wordList中每个单词的长度是一样的,所以外循环是单词的长度(在上题是固定的,为8的字符);内循环是要变化的字符的个数,就是change字符串(set去重后的),上题是固定的ACGT,为4个字符。其他是一样的。
  • 返回值:不符合条件是返回0;符合条件是返回单词接龙的长度,不是层数,单词接龙的长度就是层数+1,即返回ret+1

代码:

class Solution {
public:int ladderLength(string beginWord, string endWord, vector<string>& wordList) {unordered_map<string, int> hash;for(auto &e : wordList) hash[e]++;unordered_map<string, int> vis;if(beginWord == endWord) return 0;if(hash[endWord] == 0) return 0;// 要变化的字符string str;for (auto& e : wordList){str += e;}set<char> se(str.begin(), str.end());string change(se.begin(), se.end());//queue<string> q;int ret = 0;q.push(beginWord);while(!q.empty()){int k = q.size();ret++;while(k--){string t = q.front();if(vis[t] > 0){q.pop();continue;}vis[t]++;q.pop();for(int i=0; i<wordList[0].size(); i++){string tmp = t;for(int j=0; j<change.size(); j++){tmp[i] = change[j];if(hash[tmp] > 0 && vis[tmp] == 0){q.push(tmp);if(tmp == endWord){return ret+1;}}  }}}}return 0;}
};

五、为高尔夫比赛砍树

题目:
在这里插入图片描述
思路:BFS+哈希表
在这里插入图片描述

  • 把二维数组中所有大于1的元素排序,每次找的元素根据排序从小到大,如上图所示,找一次相当于找一个树的最短路径,所以本题等价于多个迷宫找出口
  • 注意:是要找最小的树,然后再根据顺序往上找其他树,并不是说一定要从1开始找,因为1是地面,只是上面的栗子刚好起始点就是1;如果1和4交换,千万不能从4开始走到1,再去找2,这是错的;【0,0】是4,或者说不管是多少,直接去找最小的树就行了(上面的栗子最小的树是2);如果【0,0】起始点就是最小的树,也不影响,代码中有加判断跳过,然后找次小的树(次小的树这时变成最小的树),剩下找的过程是正常的(总之:开始找最小的树ret开始计算)
  • 最后flag的处理问题:只要有走到目标树,就不会经过最后的flag,如果有经过最后的flag,说明无路可走(周围都是围墙),这时就有可能还有树没有砍掉,结果返回-1;但是有一个情况例外,当只剩下一个树了,那它周围也就没有树了,会经过flag,可是这种情况是对的,不能当作错误的情况处理;可以加个条件:下标i 等于gsz时,代表是最后一个树,不进入flag的处理

代码:

class Solution {
public: int ret = 0;// 返回值-步数int flag = 0;// 标记-是否将所有的树砍掉int n, m;// 矩阵行列int gx = 0, gy = 0;// 开始的位置,后面会更新int i = 0;// 下标-从小到大int gsz = 0;// 树的个数int bx[4] = {-1,1,0,0};int by[4] = {0,0,-1,1};int cutOffTree(vector<vector<int>>& forest) {if(forest[gx][gy] == 0) return -1;n = forest.size();m = forest[0].size();vector<int> v;for(int i=0; i<n; i++){for(int j=0; j<m; j++){if(forest[i][j] > 1)// 找树{v.push_back(forest[i][j]);}}}sort(v.begin(), v.end());// 从最小的树开始,或者找到最小树int sz = v.size();gsz = sz;// 全局的树的个数while(sz--){bfs(forest, v[i]);if(flag == 1) return -1;// 还有树没有砍完i++;// 到下一个树}return ret;}void bfs(vector<vector<int>>& forest, int tar){if(tar == forest[gx][gy])// 要找的树就是当前位置{return;}// 不是全局的,每次层序要更新(找一个树)bool vis[50][50] = {false};queue<pair<int, int>> q;q.push({gx, gy});while(!q.empty()){int k = q.size();ret++;while(k--){int x1 = q.front().first;int y1 = q.front().second;if(vis[x1][y1])// 防止重复{q.pop();continue;}q.pop();vis[x1][y1] = true;for(int i=0;i<4;i++){int x2 = x1+bx[i];int y2 = y1+by[i];if(x2>=0&&x2<n&&y2>=0&&y2<m&&forest[x2][y2]!=0&&!vis[x2][y2]){q.push({x2, y2});// 找到目标树if(forest[x2][y2] == tar){gx = x2;// 更新,下次就是从该位置开始gy = y2;return;}}}}}if(i != gsz-1) // 最后一个flag = 1;}
};

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

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

相关文章

Google Cloud Database Option(数据库选项说明)

关系数据库 在关系数据库中&#xff0c;信息存储在表、行和列中&#xff0c;这通常最适合结构化数据。因此&#xff0c;它们用于数据结构不经常更改的应用程序。与大多数关系数据库交互时使用 SQL&#xff08;结构化查询语言&#xff09;。它们为数据提供 ACID 一致性模式&am…

【Java 学习】面向程序的三大特性:封装、继承、多态

引言 1. 封装1.1 什么是封装呢&#xff1f;1.2 访问限定符1.3 使用封装 2. 继承2.1 为什么要有继承&#xff1f;2.2 继承的概念2.3 继承的语法2.4 访问父类成员2.4.1 子类中访问父类成员的变量2.4.2 访问父类的成员方法 2.5 super关键字2.6 子类的构造方法 3. 多态3.1 多态的概…

PAT甲级-1114 Family Property

题目 题目大意 共有n个户主&#xff0c;每个户主的房产按照“ 户主id 父亲id 母亲id 孩子个数 孩子的id 房产数 房产面积 ”的格式给出。如果父亲或母亲不存在&#xff0c;值为-1。每个户主及其父亲母亲孩子可以构成一个家庭&#xff0c;不同户主如果有相同的家人&#xff0c;…

如何不重启修改K8S containerd容器的内存限制(Cgroup方法)

1. 使用crictl 查看容器ID crictl ps2. 查看Cgroup位置 crictl inspect 容器ID3. 到容器Cgroup的目录下 使用上个命令就能找到CgroupPath 4 . 到cgroup目录下 正确目录是 : /sys/fs/cgroup/memory/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podf68e18…

《计算机视觉:瓶颈之辩与未来之路》

一、计算机视觉的崛起 计算机视觉是使用计算机模仿人类视觉系统的科学&#xff0c;让计算机拥有类似人类提取、处理、理解和分析图像以及图像序列的能力。它是一个多学科交叉的领域&#xff0c;与机器视觉、图像处理、人工智能、机器学习等领域密切相关。 计算机视觉行业可分为…

Burp suite2 (泷羽sec)

声明 学习视频来自B站UP主 泷羽sec,如涉及侵泷羽sec权马上删除文章。 笔记只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 这节课旨在扩大自己在网络安全方面的知识面&#xff0c;了解网络安全领域的见闻&#xff0c;了…

Scala中求汉罗塔游戏

记&#xff1a;f(n,"A","B","C")表示n个盘子从A柱子上移动到C柱子上&#xff0c;借用B柱子的过程 f(要移动的盘子的个数&#xff0c;起点&#xff0c;辅助柱子&#xff0c;终点) 1.基本情况(直接能求的)&#xff1a;f(1,"A",&…

mac 安装CosyVoice (cpu版本)

CosyVoice 介绍 CosyVoice 是阿里研发的一个tts大模型 官方项目地址&#xff1a;https://github.com/FunAudioLLM/CosyVoice.git 下载项目&#xff08;非官方&#xff09; git clone --recursive https://github.com/v3ucn/CosyVoice_for_MacOs.git 进入项目 cd CosyVoic…

C++50道经典面试题

文章结尾有最新热度的文章,感兴趣的可以去看看。 本文是经过严格查阅相关权威文献和资料,形成的专业的可靠的内容。全文数据都有据可依,可回溯。特别申明:数据和资料已获得授权。本文内容,不涉及任何偏颇观点,用中立态度客观事实描述事情本身 导读 作为一种通用且面向对…

家里养几条金鱼比较好?

金鱼&#xff0c;作为备受喜爱的家庭水族宠物&#xff0c;其饲养数量一直是众多养鱼爱好者关注的焦点。究竟养几条金鱼最为适宜&#xff0c;实则需要综合考量多方面因素&#xff0c;方能达到美观、健康与和谐的理想养鱼境界。 从风水文化的视角来看&#xff0c;金鱼数量有着诸…

启明智显ZX7981PC:5G时代的新选择,全屋网络无缝覆盖

在这个飞速发展的5G时代&#xff0c;每一个细微的科技进步都在推动着我们的生活向更加智能、便捷的方向发展。近日&#xff0c;启明智显再次引领科技潮流&#xff0c;正式发布其最新的5G CPE产品——ZX7981PC。作为继7981PG与7981PM之后的又一次迭代升级&#xff0c;ZX7981PC凭…

MATLAB四种逻辑运算

MATLAB中的四种逻辑运算包括逻辑与用&或 a n d 表示 ( 全为 1 时才为 1 &#xff0c;否则为 0 ) and表示(全为1时才为1&#xff0c;否则为0) and表示(全为1时才为1&#xff0c;否则为0)&#xff0c;逻辑或用|或 o r 表示 ( 有 1 就为 1 &#xff0c;都为 0 才为 0 ) or表示…

讲解如何使用NLTK?外加数据清理实例演示

一、如何使用NLTK&#xff1f; 定义&#xff1a;自然语言工具包&#xff08;Natural Language Toolkit&#xff09;&#xff0c;它是一个将学术语言技术应用于文本数据集的 Python 库&#xff0c;称为“文本处理”的程序设计是其基本功能&#xff0c;专门用于研究自然语言的语…

【PlantUML系列】状态图(六)

一、状态图的组成部分 状态&#xff1a;对象在其生命周期内可能处于的条件或情形&#xff0c;使用 state "State Name" as Statename 表示。初始状态&#xff1a;表示对象生命周期的开始&#xff0c;使用 [*] 表示。最终状态&#xff1a;表示对象生命周期的结束&…

ARM循环程序和子程序设计

1、计算下列两组数据的累加和并存入到sum1和 sum2 单元中。datal:0x12,0x935,0x17,0x100,0x95,0x345。 data2:0x357,0x778,0x129,0x188,0x190,0x155,0x167。 1.定义数据段 ;定义数据段&#xff0c;类型为data(表示为数据段)&#xff0c;权限为可读可写(程序可以读取和修改这…

【Vue3进阶】组件通信进阶使用方法——defineProps、defineExpose、defineEmits

组件通信 父传子 defineProps 在 Vue 3 中&#xff0c;defineProps 是一个用于在 <script setup> 语法中定义组件的 props 的函数。这个函数提供了一种更加明确和类型安全的方式来定义子组件的 props&#xff0c;使得子父组件之间的数据传递更加清晰和可维护。以下是 …

day11 性能测试(4)——Jmeter使用(黑马的完结,课程不全)直连数据库+逻辑控制器+定时器

【没有所谓的运气&#x1f36c;&#xff0c;只有绝对的努力✊】 目录 1、复习 1.1 断言&#xff08;3种&#xff09; 1.2 关联&#xff08;3种&#xff09; 1.3 录制脚本 2、Jmeter直连数据库 2.1 直连数据库——使用场景 2.2 直连数据库——操作步骤 2.2.1 案例1&…

如何将CSDN的文章保存为PDF?

目录 1、打开CSDN文章2、按F12或者鼠标右键选择检查并进入控制台3、在控制台输入以下代码4、然后回车&#xff08;Enter&#xff09;如果纵向显示不全就横向 1、打开CSDN文章 2、按F12或者鼠标右键选择检查并进入控制台 3、在控制台输入以下代码 (function(){ $("#side&q…

ubuntu22.04 使用crash

文章目录 前言一、apt 安装dbgsym vnlinux二、使用.ddeb包安装dbgsym vnlinux三、dbgsym发行版四、crash调试参考资料 前言 最近在适配 ubuntu系统&#xff0c;记录一下其crash的安装。 一、apt 安装dbgsym vnlinux # echo "deb http://ddebs.ubuntu.com $(lsb_release…

刷题日志【4】

目录 1、猜数字大小 1、猜数字大小 题意有点抽象&#xff0c;我大概讲一下&#xff0c;就是在1——n里面会有一个目标数&#xff0c;我们通过猜数字的方式逼近这个数字&#xff0c;直到解出这个数&#xff0c;之前我们是用二分法求最快达到求解的问题&#xff0c;这道题多了每…