发布于 

多源广度优先搜索

广度优先搜索进阶题目

简单而言,多源广度优先搜索的起始节点比较多,与普通的广度优先搜索不同,多源强调的是开始搜索的源头不是1,在初始将起点放入待搜索队列时,需要将所有符合条件的待搜索节点全部入队

核心做法

在初次遍历整张图的时候,将所有符合条件的待搜索节点(源节点)放入队列中,每次取出节点后都需要搜索当前节点的上下左右四方向,将访问过的节点给予已访问的标记,再将搜索到符合条件的所有节点进行相关的判断修改操作后,将符合搜索条件的节点入队

01 矩阵

解题思路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class Solution {
public int[][] updateMatrix(int[][] mat) {
// 该问题需要使用多源BFS的思路进行求解
// 通过dirs简化四个方向移动的代码
int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int m = mat.length;
int n = mat[0].length;
int[][] res = new int[m][n];
// 深度优先搜索的队列
Queue<int[]> queue = new LinkedList<>();
// 用来记录元素是否已经被访问
boolean[][] finds = new boolean[m][n];

//将所有源点放入队列
for(int i=0;i<mat.length;i++){
for(int j=0;j<mat[0].length;j++){
if(mat[i][j] == 0){
queue.offer(new int[]{i,j});
finds[i][j] = true;
}
}
}

while(!queue.isEmpty()){
// 从队中取出节点
int[] position = queue.poll();
int i = position[0],j = position[1];
for(int k=0;k<4;++k){
// 移动四个方向
int ni = i + dirs[k][0];
int nj = j + dirs[k][1];
if(ni>=0 && ni<m && nj>=0 && nj<n && !finds[ni][nj]){
// 判断边界 执行搜索后的逻辑
res[ni][nj] = res[i][j] + 1;
// 新的节点入队
queue.offer(new int[]{ni,nj});
// 将当前位置标记为已访问
finds[ni][nj] = true;
}
}
}

return res;
}
}

994. 腐烂的橘子

解题思路

首先将所有的腐烂橘子的位置放入队列中,并且记录此时新鲜水果的数量与腐烂水果的数量,之后执行一次判断,若当前已经没有水果,直接返回0,否则开始腐烂的过程,腐烂的过程即是向腐烂水果的上下左右进行搜索,若发现新鲜的水果就将其腐蚀,由于本轮需要统计腐蚀水果的轮次,在出队时按照每轮放入的节点进行类似层序遍历的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class Solution {
public int orangesRotting(int[][] grid) {
int[][] dirs = new int[][]{{0,1},{0,-1},{1,0},{-1,0}};
int m = grid.length, n=grid[0].length;
boolean[][] seen = new boolean[m][n];
Queue<int[]> queue = new LinkedList<>();
int numFresh = 0;
int numRotted = 0;
int step = 0;
//将图中所有腐烂橘子进队
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(grid[i][j]==2){
numRotted++;
queue.offer(new int[]{i,j});
seen[i][j] = true;
}
if(grid[i][j]==1){
numFresh++;
}
}
}

//判断当前图中是否没有水果
if (numRotted == 0 && numFresh == 0) return 0;

//执行腐烂的过程
while(!queue.isEmpty()){
step++;
int size = queue.size();
for(int num = 0;num<size;size--){
int[] pos = queue.poll();
int i = pos[0],j = pos[1];
for(int d=0;d<4;d++){
int ni = i + dirs[d][0];
int nj = j + dirs[d][1];
if(ni>=0 && ni<m && nj>=0 && nj<n && !seen[ni][nj]){
if(grid[ni][nj] == 1){
grid[ni][nj] = 2;
numFresh--;
queue.offer(new int[]{ni,nj});
}
seen[ni][nj] = true;
}
}
}
}
//若当前图中存在新鲜水果 返回-1
if(numFresh!=0){
return -1;
}else{
//原始节点出队不算腐蚀过程 故该位置需要-1
return step-1;
}
}
}

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 @John Doe 创建,使用 Stellar 作为主题。