文章目录
- 前言
- 单源BFS例题
- 一、迷宫中离入口最近的出口
- 二、 最小基因变化
- 三、单词接龙
- 四、为高尔夫比赛砍树
- 多源BFS例题
- 一、 01 矩阵
- 二、飞地的数量
- 三、地图中的最高点
- 四、地图分析
- 结语
前言
什么是单源、多源BFS算法问题呢?
BFS(Breadth - First Search)即广度优先搜索算法,单源和多源 BFS 算法问题主要用于解决图或网格中的最短路径问题 ,二者具体介绍如下:
单源 BFS 算法问题:指从图中的一个起始节点(源点)出发,按照广度优先的策略,逐层向外扩展访问其他节点,找到从该源点到图中其他各个可达节点的最短路径。例如在一个迷宫网格中,从一个特定入口出发找出口,就可以使用单源 BFS。该算法适用于无权图或所有边权值都相同的图。它利用队列来存储待访问节点,先将源点入队,然后不断取出队首节点并访问其相邻未访问节点,将这些相邻节点入队,直到队列为空或找到目标节点。
多源 BFS 算法问题:是有多个起始节点(源点),目标是找到从这些多个源点到图中其他各个可达节点的最短路径。例如在一个城市地图中,有多个垃圾回收站(源点),要计算各个小区到最近垃圾回收站的距离,就可能用到多源 BFS。多源 BFS 的核心在于初始化队列时将所有源点都放入队列,之后和单源 BFS 类似,按广度优先顺序访问节点并扩展,直到遍历完所有可达节点。它也主要用于边权为 1 或边权相等的情况 。
解决多源 BFS 问题时,若直接转化为若干个单源最短路问题求解,可能因重复查找过多而超时。更好的方法是把所有源点视为一个 “超级源点” ,将问题转化为单源最短路问题来处理。
下面,本片文章将通过例题为大家详细介绍单源、多源BFS算法!
单源BFS例题
一、迷宫中离入口最近的出口
- 题目链接:迷宫中离入口最近的出口
- 题目描述:
给你⼀个 m x n 的迷宫矩阵 maze (下标从 0 开始),矩阵中有空格⼦(⽤ ‘.’ 表示)和墙(⽤ ‘+’ 表示)。同时给你迷宫的⼊⼝ entrance ,用 entrance = [entrancerow, entrancecol] 表示你⼀开始所在格子的行和列。 每⼀步操作,你可以往上,下,左或者右移动⼀个格子。你不能进⼊墙所在的格子,你也不能离开迷宫。你的目标是找到离 entrance 最近 的出口。出口的含义是 maze 边界上的空格子。
entrance 格子不算出口。 请你返回从 entrance 到最近出⼝的最短路径的步数 ,如果不存在这样的路径,请你返回 -1 。
⽰例 1:
输⼊:maze = [[“+”,“+”,“.”,“+”],[“.”,“.”,“.”,“+”],[“+”,“+”,“+”,“.”]], entrance = [1,2]
输出:1
解释:总共有 3 个出⼝,分别位于 (1,0),(0,2) 和 (2,3) 。 ⼀开始,你在⼊⼝格⼦ (1,2) 处。
◦ 你可以往左移动 2 步到达 (1,0) 。
◦ 你可以往上移动 1 步到达 (0,2) 。 从入口处没法到达 (2,3) 。
所以,最近的出口是 (0,2) ,距离为 1 步。
⽰例 2:
输⼊:maze = [[“+”,“+”,“+”],[“.”,“.”,“.”],[“+”,“+”,“+”]], entrance = [1,0]
输出:2
解释:迷宫中只有 1 个出口,在 (1,2) 处。(1,0) 不算出口,因为它是入口格⼦。 初始时,你在入口与格⼦ (1,0) 处。
◦ 你可以往右移动 2 步到达 (1,2) 处。 所以,最近的出口为 (1,2) ,距离为 2 步。
⽰例 3:
输⼊:maze = [[“.”,“+”]], entrance = [0,0]
输出:-1
解释:这个迷宫中没有出⼝。
提示:
maze.length == m
maze[i].length == n
1 <= m, n <= 100
maze[i][j] 要么是 ‘.’ ,要么是 ‘+’ 。
entrance.length == 2
0 <= entrancerow < m
0 <= entrancecol < n
entrance ⼀定是空格子。
-
解法(bfs 求最短路):
算法思路: 利⽤层序遍历来解决迷宫问题,是最经典的做法。 我们可以从起点开始层序遍历,并且在遍历的过程中记录当前遍历的层数。这样就能在找到出口的时候,得到起点到出口的最短距离。 -
代码示例:
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[200][200];
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;
}
二、 最小基因变化
- 题目链接:最小基因变化
- 题目描述:
基因序列可以表示为⼀条由 8 个字符组成的字符串,其中每个字符都是 ‘A’ 、 ‘C’ 、 ‘G’ 和’T’ 之⼀。 假设我们需要调查从基因序列 start 变为 end 所发⽣的基因变化。⼀次基因变化就意味着这个 基因序列中的⼀个字符发⽣了变化。
• 例如, “AACCGGTT” --> “AACCGGTA” 就是⼀次基因变化。 另有⼀个基因库 bank 记录了所有有效的基因变化,只有基因库中的基因才是有效的基因序列。 (变化后的基因必须位于基因库 bank 中) 给你两个基因序列 start 和 end ,以及⼀个基因库 bank ,请你找出并返回能够使 start变化为 end 所需的最少变化次数。如果无法完成此基因变化,返回 -1 。
注意:起始基因序列 start 默认是有效的,但是它并不⼀定会出现在基因库中
示例 1:
输入:start = “AACCGGTT”, end = “AACCGGTA”, bank = [“AACCGGTA”]
输出:1
⽰例 2:
输⼊:start = “AACCGGTT”, end = “AAACGGTA”, bank =
[“AACCGGTA”,“AACCGCTA”,“AAACGGTA”]
输出:2
⽰例 3:
输入:start = “AAAAACCC”, end = “AACCCCCC”, bank =[“AAAACCCC”,“AAACCCCC”,“AACCCCCC”]
输出:3
提示:
◦ start.length == 8
◦ end.length == 8
◦ 0 <= bank.length <= 10
◦ bank[i].length == 8
◦ start 、 end 和 bank[i] 仅由字符 [‘A’, ‘C’, ‘G’, ‘T’] 组成
-
解法:
算法思路: 如果将「每次字符串的变换」抽象成图中的「两个顶点和⼀条边」的话,问题就变成了「边权为 1 的最短路问题」。
因此,从起始的字符串开始,来⼀次 bfs 即可。 -
代码示例:
int[] dx = {0, 0, -1, 1};
int[] dy = {1, -1, 0, 0};
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[] charge = {'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] = charge[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;
}
三、单词接龙
- 题目链接:单词接龙
- 题目描述:
字典 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 。
⽰例 1:
输⼊:beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]
输出:5
解释:⼀个最短转换序列是 “hit” -> “hot” -> “dot” -> “dog” -> “cog”, 返回它的长度 5。
⽰例 2:
输⼊:beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”]
输出:0
解释:endWord “cog” 不在字典中,所以无法进行转换。
提示:
◦ 1 <= beginWord.length <= 10
◦ endWord.length == beginWord.length
◦ 1 <= wordList.length <= 5000
◦ wordList[i].length == beginWord.length
◦ beginWord 、 endWord 和 wordList[i] 由⼩写英⽂字⺟组成 ◦ beginWord != endWord
◦ wordList 中的所有字符串互不相同
- 解法:
算法思路:本题的算法思路与上题相似,大家可以自行尝试编写代码提高代码能力。 - 代码示例:
int[] dx = {0, 0, -1, 1};
int[] dy = {1, -1, 0, 0};
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<>();
vis.add(beginWord);
q.add(beginWord);
int ret = 1;
while (!q.isEmpty()) {
ret++;
int size = q.size();
while (size-- != 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;
}
四、为高尔夫比赛砍树
- 题目链接:为高尔夫比赛砍树
- 题目描述:
你被请来给⼀个要举办高尔夫比赛的树林砍树。树林由⼀个 m x n 的矩阵表示, 在这个矩阵中:
◦ 0 表⽰障碍,无法触碰
◦ 1 表示地⾯,可以行走
◦ ⽐ 1 ⼤的数 表⽰有树的单元格,可以行走,数值表⽰树的⾼度
每⼀步,你都可以向上、下、左、右四个⽅向之⼀移动⼀个单位,如果你站的地方有⼀棵树,那么你 可以决定是否要砍倒它。 你需要按照树的高度从低向⾼砍掉所有的树,每砍过⼀颗树,该单元格的值变为 1 (即变为地面)。你将从 (0, 0) 点开始工作,返回你砍完所有树需要走的最小步数。 如果你⽆法砍完所有的树,返回 -1 。 可以保证的是,没有两棵树的⾼度是相同的,并且你至少需要砍倒⼀棵树。
⽰例 1:
输⼊:forest = [[1,2,3],[0,0,4],[7,6,5]]
输出:6
解释:沿着上⾯的路径,你可以⽤ 6 步,按从最矮到最⾼的顺序砍掉这些树。
⽰例 2:
输⼊:forest = [[1,2,3],[0,0,0],[7,6,5]]
输出:-1
解释:由于中间⼀⾏被障碍阻塞,⽆法访问最下⾯⼀⾏中的树。
示例 3:
输入:forest = [[2,3,4],[0,0,5],[8,7,6]]
输出:6
解释:可以按与⽰例 1 相同的路径来砍掉所有的树
提⽰:
◦ m == forest.length
◦ n == forest[i].length
◦ 1 <= m, n <= 50
◦ 0 <= forest[i][j] <= 10^9
- 解法:
a. 先找出砍树的顺序;
b. 然后按照砍树的顺序,⼀个⼀个的⽤ bfs 求出最短路即可 - 代码示例:
int m, n;
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
public int cutOffTree(List<List<Integer>> f) {
m = f.size();
n = f.get(0).size();
//准备工作:确定看书顺序
List<int[]> trees = new ArrayList<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (f.get(i).get(j) > 1) {
trees.add(new int[]{i, j});
}
}
}
Collections.sort(trees, (a, b) -> {
return f.get(a[0]).get(a[1]) - f.get(b[0]).get(b[1]);
});
//按照顺序砍树
int ret = 0;
int bx = 0, by = 0;
for (int[] tree : trees) {
int x = tree[0], y = tree[1];
int step = bfs(f, bx, by, x, y);
if (step == -1) return -1;
ret += step;
bx = x;
by = y;
}
return ret;
}
public int bfs(List<List<Integer>> f, int bx, int by, int ex, int ey) {
if (bx == ex && by == ey) {
return 0;
}
Queue<int[]> q = new LinkedList<>();
boolean[][] vis = new boolean[m][n];
q.add(new int[]{bx, by});
vis[bx][by] = true;
int step = 0;
while (!q.isEmpty()) {
step++;
int sz = q.size();
while (sz-- != 0) {
int[] t = q.poll();
int a = t[0], b = t[1];
for (int i = 0; i < 4; i++) {
int x = a + dx[i], y = b + dy[i];
if (x >= 0 && x < m && y >= 0 && y < n && f.get(x).get(y) != 0 && !vis[x][y]) {
if (x == ex && y == ey) {
return step;
}
vis[x][y] = true;
q.add(new int[]{x, y});
}
}
}
}
return -1;
}
多源BFS例题
一、 01 矩阵
- 题目链接:01矩阵
- 题目描述:
给定⼀个由 0 和 1 组成的矩阵 mat ,请输出⼀个⼤⼩相同的矩阵,其中每⼀个格子是mat 中对应位置元素到最近的 0 的距离。
两个相邻元素间的距离为 1 。
示例 1:
输⼊:mat = [[0,0,0],[0,1,0],[0,0,0]]
输出:[[0,0,0],[0,1,0],[0,0,0]]
示例 2:
输入:mat = [[0,0,0],[0,1,0],[1,1,1]]
输出:[[0,0,0],[0,1,0],[1,2,1]]
提⽰:
m == mat.length
n == mat[i].length
1 <= m, n <= 104
1 <= m * n <= 104
mat[i][j] is either 0 or 1.
mat 中⾄少有⼀个 0
- 解法(bfs)(多个源头的最短路问题)
算法思路: 对于求的最终结果,我们有两种方式:
• 第⼀种⽅式:从每⼀个 1 开始,然后通过层序遍历找到离它最近的 0 。 这⼀种⽅式,我们会以所有的 1 起点,来⼀次层序遍历,势必会遍历到很多重复的点。并且如果 矩阵中只有⼀个 0 的话,每⼀次层序遍历都要遍历很多层,时间复杂度较⾼。
• 换⼀种⽅式:从 0 开始层序遍历,并且记录遍历的层数。当第⼀次碰到 1 的时候,当前的层数 就是这个 1 离 0 的最短距离。 这⼀种方式,我们在遍历的时候标记⼀下处理过的 1 ,能够做到只⽤遍历整个矩阵⼀次,就能得 到最终结果。
但是,这里有⼀个问题, 0 是有很多个的,我们怎么才能保证遇到的 1 距离这⼀个 0 是最近的呢?
其实很简单,我们可以先把所有的 0 都放在队列中,把它们当成⼀个整体,每次把当前队列⾥⾯的所 有元素向外扩展⼀次。 - 代码示例:
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
public int[][] updateMatrix(int[][] mat) {
int m = mat.length;
int n = mat[0].length;
int[][] dist = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
dist[i][j] = -1;
}
}
Queue<int[]> q = new LinkedList<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (mat[i][j] == 0) {
dist[i][j] = 0;
q.add(new int[]{i, j});
}
}
}
while (!q.isEmpty()) {
int[] t = q.poll();
int a = t[0];
int b = t[1];
for (int i = 0; i < 4; i++) {
int x = a + dx[i], y = b + dy[i];
if (x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1) {
dist[x][y] = dist[a][b] + 1;
q.add(new int[]{x, y});
}
}
}
return dist;
}
二、飞地的数量
- 题目链接:飞地的数量
- 题目描述:
给你⼀个大小为 m x n 的⼆进制矩阵 grid ,其中 0 表示⼀个海洋单元格、 1 表示⼀个陆地 单元格。 ⼀次移动是指从⼀个陆地单元格走到另⼀个相邻(上、下、左、右)的陆地单元格或跨过 grid的边界。 返回网格中无法在任意次数的移动中离开⽹格边界的陆地单元格的数量。
示例一:
输⼊:grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
输出:3
解释:有三个 1 被 0 包围。⼀个 1 没有被包围,因为它在边界上。
示例 2:
输⼊:grid = [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]]
输出:0
解释:所有 1 都在边界上或可以到达边界。
提⽰:
◦ m == grid.length
◦ n == grid[i].length
◦ 1 <= m, n <= 500
◦ grid[i][j] 的值为 0 或 1
- 解法:
算法思路: 正难则反: 从边上的 1 开始搜索,把与边上 1 相连的联通区域全部标记⼀下; 然后再遍历⼀遍矩阵,看看哪些位置的 1 没有被标记即可 标记的时候,可以用「多源 bfs 」解决。 - 代码示例:
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
public int numEnclaves(int[][] grid) {
int m = grid.length, n = grid[0].length;
Queue<int[]> q = new LinkedList<>();
boolean[][] vis = new boolean[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i == 0 || i == m - 1 || j == 0 || j == n - 1) {
if (grid[i][j] == 1) {
q.add(new int[]{i, j});
vis[i][j] = true;
}
}
}
}
while (!q.isEmpty()) {
int[] t = q.poll();
int a = t[0], b = t[1];
for (int i = 0; i < 4; i++) {
int x = a + dx[i], y = b + dy[i];
if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 && !vis[x][y]) {
vis[x][y] = true;
q.add(new int[]{x, y});
}
}
}
int ret = 0;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (grid[i][j] == 1 && !vis[i][j])
ret++;
return ret;
}
三、地图中的最高点
- 题目链接:地图中的最高点
- 题目描述:
给你⼀个大小为 m x n 的整数矩阵 isWater ,它代表了⼀个由陆地 和水域 单元格组成的地图。
• 如果 isWater[i][j] == 0 ,格子(i, j) 是⼀个陆地格⼦。
• 如果 isWater[i][j] == 1 ,格子(i, j) 是⼀个水域格⼦。 你需要按照如下规则给每个单元格安排高度:
• 每个格⼦的高度都必须是非负的。
• 如果⼀个格子是水域 ,那么它的高度必须为 0 。
• 任意相邻的格高度差至多 为 1 。当两个格子在正东、南、西、北方向上相互紧挨着,就称它们为相邻的格⼦。(也就是说它们有⼀条公共边) 找到⼀种安排高度的方案,使得矩阵中的最高高度值最大 。 请你返回⼀个大小为 m x n 的整数矩阵 height ,其中 height[i][j] 是格⼦ (i, j) 的高度。如果有多种解法,请返回任意⼀个 。
示例 1:
输入:isWater = [[0,1],[0,0]]
输出:[[1,0],[2,1]]
解释:上图展示了给各个格⼦安排的高度。 蓝⾊格子是水域格,绿色格子是陆地格。
示例二:
输⼊:isWater = [[0,0,1],[1,0,0],[0,0,0]]
输出:[[1,1,0],[0,1,1],[1,2,2]]
解释:所有安排⽅案中,最⾼可行高度为 2 。 任意安排方案中,只要最高高度为 2 且符合上述规则的,都为可行方案。
提示:
◦ m == isWater.length
◦ n == isWater[i].length
◦ 1 <= m, n <= 1000
◦ isWater[i][j] 要么是 0 ,要么是 1 。 ◦
⾄少有 1 个水域格子。
- 解法: 算法思路:
01矩阵的变型题,直接用多源 bfs 解决即可。 - 代码示例:
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
public int[][] highestPeak(int[][] isWater) {
int m = isWater.length, n = isWater[0].length;
int[][] dist = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
dist[i][j] = -1;
}
}
Queue<int[]> q = new LinkedList<>();
//所有的源点加入到序列里
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (isWater[i][j] == 1) {
q.add(new int[]{i, j});
dist[i][j] = 0;
}
}
}
while (!q.isEmpty()) {
int[] t = q.poll();
int a = t[0], b = t[1];
for (int i = 0; i < 4; i++) {
int x = a + dx[i], y = b + dy[i];
if (x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1) {
dist[x][y] = dist[a][b] + 1;
q.add(new int[]{x, y});
}
}
}
return dist;
}
四、地图分析
- 题目链接:地图分析
- 题目描述:
你现在⼿⾥有⼀份⼤⼩为 n x n 的网格 grid ,上⾯的每个 单元格 都⽤ 0 和 1 标记好了。 其中 0 代表海洋, 1 代表陆地。 请你找出⼀个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的,并返回该距离。如果网格上只有陆地或者海洋,请返回 -1 。
我们这里说的距离是「曼哈顿距离」( Manhattan Distance): (x0, y0) 和 (x1, y1) 这两 个单元格之间的距离是 |x0 - x1| + |y0 - y1|
示例 1:
输入:grid = [[1,0,1],[0,0,0],[1,0,1]]
输出:2
解释:
海洋单元格 (1, 1) 和所有陆地单元格之间的距离都达到最大,最大距离为 2
⽰例 2:
输⼊:grid = [[1,0,0],[0,0,0],[0,0,0]]
输出:4
解释:
海洋单元格 (2, 2) 和所有陆地单元格之间的距离都达到最⼤,最大距离为 4。
提示:
◦ n == grid.length
◦ n == grid[i].length
◦ 1 <= n <= 100
◦ grid[i][j] 不是 0 就是 1
-
解法:
算法思路:
01矩阵的变型题,直接用多源 bfs 解决即可。 -
代码示例:
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
public int maxDistance(int[][] grid) {
int ret = -1;
int m = grid.length, n = grid[0].length;
int[][] dist = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
dist[i][j] = -1;
}
}
Queue<int[]> q = new LinkedList<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
dist[i][j] = 0;
q.add(new int[]{i, j});
}
}
}
while (!q.isEmpty()) {
int[] t = q.poll();
int a = t[0], b = t[1];
for (int i = 0; i < 4; i++) {
int x = a + dx[i], y = b + dy[i];
if (x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1) {
dist[x][y] = dist[a][b] + 1;
ret = Math.max(ret, dist[x][y]);
q.add(new int[]{x, y});
}
}
}
return ret;
}
结语
本文到这里就结束了,主要介绍了解决单源多源BFS问题,并通过例题深化了代码步骤,本篇文章题目十分考验代码能力,大家一定要自己尝试哦!
以上就是本文全部内容,感谢各位能够看到最后,创作不易,希望大家多多支持!
最后,大家再见!祝好!我们下期见!