BFS 解决最短路问题详解

news/2024/9/28 18:12:48 标签: 宽度优先

BFS 解决最短路问题

    • 题目一:迷宫中离⼊⼝最近的出⼝
      • 1. 题⽬链接:
      • 2. 题⽬描述:
      • 3.算法思路:
      • 4.代码
    • 题目二. 最⼩基因变化
      • 1. 题⽬链接:
      • 2. 题⽬描述:
      • 3.算法思路:
      • 4.代码
    • 题目三:单词接⻰
      • 1. 题⽬链接:
      • 2. 题⽬描述:
      • 3.算法思路:
      • 4.代码

题目一:迷宫中离⼊⼝最近的出⼝

1. 题⽬链接:

https://leetcode.cn/problems/nearest-exit-from-entrance-in-maze/description/

2. 题⽬描述:

给你⼀个 m x n 的迷宫矩阵 maze (下标从 0 开始),矩阵中有空格⼦(⽤ ‘.’ 表⽰)和墙(⽤ ‘+’ 表
⽰)。同时给你迷宫的⼊⼝ entrance ,⽤ entrance = [entrancerow, entrancecol] 表⽰你⼀开始所在格⼦的⾏和列。 每⼀步操作,你可以往 上,下,左 或者 右 移动⼀个格⼦。你不能进⼊墙所在的格⼦,你也不能离开 迷宫。你的⽬标是找到离 entrance 最近 的出⼝。出⼝ 的含义是 maze 边界 上的 空格⼦。 entrance 格⼦ 不算 出⼝。 请你返回从 entrance 到最近出⼝的最短路径的 步数 ,如果不存在这样的路径,请你返回 -1 。

在这里插入图片描述

3.算法思路:

利⽤层序遍历来解决迷宫问题,是最经典的做法。 我们可以从起点开始层序遍历,并且在遍历的过程中记录当前遍历的层数。这样就能在找到出⼝的
时候,得到起点到出⼝的最短距离。

4.代码

class Solution 
{
 int[] dx = {0, 0, -1, 1};

 int[] dy = {1, -1, 0, 0};
 public int nearestExit(char[][] maze, int[] e) 
 {
 int m = maze.length, n = maze[0].length;
 boolean[][] vis = new boolean[m][n];
 Queue<int[]> q = new LinkedList<>();
 q.add(new int[]{e[0], e[1]});
 vis[e[0]][e[1]] = true;
 int step = 0;
 while(!q.isEmpty())
 {
 step++;
 int sz = q.size();
 for(int i = 0; i < sz; i++)
 {
 int[] t = q.poll();
 int a = t[0], b = t[1];
 for(int j = 0; j < 4; j++)
 {
 int x = a + dx[j], y = b + dy[j];
 if(x >= 0 && x < m && y >= 0 && y < n && maze[x][y] == '.' 
&& !vis[x][y])
 {
 // 判断是否已经到出⼝ 
 if(x == 0 || x == m - 1 || y == 0 || y == n - 1) return

 step;
 vis[x][y] = true;
 q.add(new int[]{x, y});
 }
 }
 }
 }
 return -1;
 }
}

题目二. 最⼩基因变化

1. 题⽬链接:

https://leetcode.cn/problems/minimum-genetic-mutation/description/

2. 题⽬描述:

基因序列可以表⽰为⼀条由 8 个字符组成的字符串,其中每个字符都是 ‘A’ 、 ‘C’ 、 ‘G’ 和 ‘T’ 之⼀。
假设我们需要调查从基因序列 start 变为 end 所发⽣的基因变化。⼀次基因变化就意味着这个 基因序列中的⼀个字符发⽣了变化。

• 例如, “AACCGGTT” --> “AACCGGTA” 就是⼀次基因变化。 另有⼀个基因库 bank
记录了所有有效的基因变化,只有基因库中的基因才是有效的基因序列。(变化后的基因必须位于基因库 bank 中) 给你两个基因序列 start
和 end ,以及⼀个基因库 bank ,请你找出并返回能够使 start 变化为 end 所需的最少变化次数。如果⽆法完成此基因变化,返回
-1 。 注意:起始基因序列 start 默认是有效的,但是它并不⼀定会出现在基因库中。

在这里插入图片描述

3.算法思路:

如果将「每次字符串的变换」抽象成图中的「两个顶点和⼀条边」的话,问题就变成了「边权为 1 的最短路问题」。
因此,从起始的字符串开始,来⼀次 bfs 即可。
每一次转换相当于经过一层,有这么多的情况:可以转换任意一个位置,每个位置可以转换为’A’ 、 ‘C’ 、 ‘G’ 和’T’ 之⼀的任意字符。

4.代码

class Solution 
{
 public int minMutation(String startGene, String endGene, String[] bank) 
 {
 Set<String> vis = new HashSet<>(); // ⽤来标记已经搜索过的状态 
 Set<String> hash = new HashSet<>(); // ⽤来统计基因库⾥⾯的字符串 
 for(String s : bank) hash.add(s);
 char[] change = {'A', 'C', 'G', 'T'};
 if(startGene.equals(endGene)) return 0;
 if(!hash.contains(endGene)) return -1;
 Queue<String> q = new LinkedList<>();
 q.add(startGene);
 vis.add(startGene);
 int step = 0;
 while(!q.isEmpty())
 {
 step++;
 int sz = q.size();
 while(sz-- != 0)
 {
 String t = q.poll();
 for(int i = 0; i < 8; i++)
 {
 char[] tmp = t.toCharArray();
 for(int j = 0; j < 4; j++)
 {
 tmp[i] = change[j];
 String next = new String(tmp);
 if(hash.contains(next) && !vis.contains(next))
 {
 if(next.equals(endGene)) return step;
 q.add(next);
 vis.add(next);
 }
 }
 }
 }
 }
 return -1;
 }
 }

题目三:单词接⻰

1. 题⽬链接:

https://leetcode.cn/problems/word-ladder/description/

2. 题⽬描述:

字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是⼀个按下述规格形成的序 列 beginWord
-> s(1) -> s(2) -> … -> s(k) :

• 每⼀对相邻的单词只差⼀个字⺟。

• 对于 1 <= i <= k 时,每个 s(i) 都在 wordList 中。注意, beginWord 不需要 在 wordList 中。

• s(k) == endWord 给你两个单词 beginWord 和 endWord 和⼀个字典 wordList ,返回 从beginWord 到 endWord 的 最短转换序列 中的 单词数⽬ 。如果不存在这样的转换序列,返回 0

在这里插入图片描述

3.算法思路:

和上一题一样,如果将「每次字符串的变换」抽象成图中的「两个顶点和⼀条边」的话,问题就变成了「边权为 1 的最短路问题」。
因此,从起始的字符串开始,要经过多少层才能转变为目标字符来⼀次 bfs 即可。
每一次转换相当于经过一层,有这么多的情况:可以转换任意一个位置,每个位置可以转换位为’a’到’z’的任意字符。

4.代码

class Solution 
{
 public int ladderLength(String beginWord, String endWord, List<String> 
wordList) 
 {
 Set<String> hash = new HashSet<>();
 for(String s : wordList) hash.add(s);
 Set<String> vis = new HashSet<>(); // 标记已经搜索过的单词 
 if(!hash.contains(endWord)) return 0;
 Queue<String> q = new LinkedList<>();
 q.add(beginWord);
 vis.add(beginWord);
 int ret = 1;
 while(!q.isEmpty())
 {
 ret++;
 int sz = q.size();
 while(sz-- != 0)
 {
 String t = q.poll();
 for(int i = 0; i < t.length(); i++)
 {
 char[] tmp = t.toCharArray();
 for(char ch = 'a'; ch <= 'z'; ch++)
 {
 tmp[i] = ch;
 String next = new String(tmp);
 if(hash.contains(next) && !vis.contains(next))
 {
 if(next.equals(endWord)) return ret;
 q.add(next);
 vis.add(next);
 }
 }
 }
 }
 }
 return 0;
 }
 }

http://www.niftyadmin.cn/n/5681608.html

相关文章

人只活一次,活出一道光吧

人只活一次, 你怎么舍得让自己的短暂的一生是丑陋的, 你怎么舍得让自己短暂的一生, 只是在往下坠落, 即便是坠落, 也应该具有落日般的华丽吧, 你会漫漫的活成一束光, 谁若接近你, 就是接近光, 【人人都想向上&#xff0c;人人都想老而不衰&#xff0c;但现实是当你想活成一道光…

如何使用ssm实现基于web的山东红色旅游信息管理系统的设计与实现

TOC ssm716基于web的山东红色旅游信息管理系统的设计与实现jsp 绪论 1.1研究背景 从古到今&#xff0c;信息的录入&#xff0c;存储&#xff0c;检索都受制于社会生产力的发展&#xff0c;不仅仅浪费大量的人力资源还需要浪费大量的社会物资&#xff0c;并且不能长时间的保…

C++深入学习string类成员函数(4):字符串的操作

引言 在c中&#xff0c;std::string提供了许多字符串操作符函数&#xff0c;让我们能够秦松驾驭文本数据&#xff0c;而与此同时&#xff0c;非成员函数的重载更是为string类增添了别样的魅力&#xff0c;输入输出流的重载让我们像处理基本类型的数据一样方便地读取和输出字符…

测试用例的举例

1. 基于测试公式设计测试用例 通过功能&#xff0c;性能&#xff0c;安全性&#xff0c;界面&#xff0c;安全性&#xff0c;易用&#xff0c;兼容对于一个水杯进行测试用例的设计&#xff1b; 对于一个软件的测试用例设计&#xff1a; 功能&#xff1a;软件本质上能够用来干什…

OpenHarmony(鸿蒙南向)——平台驱动开发【PIN】

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 概述 功能简介 PIN即管脚控制器&#xff0c;用于统一管理各SoC的…

HuggingFists数据服务发布--功能闭环

最近&#xff0c;HuggingFists隆重推出了新的功能模块-“数据服务”模块。该模块可以有效的解决HuggingFists算子能力不足时的扩展问题。 现实世界中&#xff0c;不管是在互联网还是组织内部的私有网络中&#xff0c;都存在着大量以Web API的形式对外开放的特有、特色功能。这些…

基于两分支卷积和 Transformer 的轻量级多尺度特征融合超分辨率网络 !

当前的单图像超分辨率&#xff08;SISR&#xff09;算法有两种主要的深度学习模型&#xff0c;一种是基于卷积神经网络&#xff08;CNN&#xff09;的模型&#xff0c;另一种是基于Transformer的模型。前者利用不同卷积核大小的卷积层堆叠来设计模型&#xff0c;使得模型能够更…

快速实现AI搜索!Fivetran 支持 Milvus 作为数据迁移目标

Fivetran 现已支持 Milvus 向量数据库作为数据迁移的目标&#xff0c;能够有效简化 RAG 应用和 AI 搜索中数据源接入的流程。 数据是 AI 应用的支柱&#xff0c;无缝连接数据是充分释放数据潜力的关键。非结构化数据对于企业搜索和检索增强生成&#xff08;RAG&#xff09;聊天…