前言:
所谓多源BFS,简单来说就从多个起点开始遍历。
一、01 矩阵
题目解析

给定一个由0和1组成的矩阵,要输出一个大小相同的矩阵,结果矩阵中每一个格子都是mat中对应位置到最近的0的距离。
算法思路
这道题如果从1位置开始遍历,那就只能一个一个进行BFS 求到最近的0的距离,那未免也太复杂的。
但如果从0位置开始遍历,我们就可以在一开始将所有的0位置放入到队列中,同时进行BFS,并且择优选择(统计每个位置是否遍历过,去重);
这样进行多源BFS后,1位置对应结果矩阵中的值就是该位置到最近0的距离。
代码实现
cpp
class Solution {
public:
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
typedef pair<int, int> PII;
vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
int n = mat.size();
int m = mat[0].size();
queue<PII> q;
vector<vector<int>> ret(n, vector<int>(m, -1));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (mat[i][j] == 0) {
q.push({i, j});
ret[i][j] = 0;
}
}
}
while(q.size() > 0)
{
int sz = q.size();
while(sz--)
{
auto [a,b] = q.front();
q.pop();
for(int i = 0;i<4;i++)
{
int x = a + dx[i];
int y = b + dy[i];
if(x>=0 && x<n && y>= 0 && y<m && ret[x][y] == -1)
{
q.push({x,y});
ret[x][y] = ret[a][b] + 1;
}
}
}
}
return ret;
}
};
二、飞地的数量
题目解析

这道题和被围绕的区域非常类似,都是找围绕的区域;这里要求被围绕区域的陆地单元格个数。
算法思路
这道题思路也很明了了,先进行边缘处理,从边缘位置中的1开始进行BFS 遍历,进行标记,然后统计没有被标记的1的个数即可。
但这里边缘位置的1有很多,这里也不需要一个一个进行BFS 遍历,直接将所有边缘的1的下标放入队列中,进行多源BFS即可。
标记边界连通的陆地
- 遍历矩阵的四条边界,将所有边界上的陆地(值为 1)加入队列,并标记为 0。
- 通过 BFS 从这些边界陆地出发,向四周扩散,将所有能连通到边界的陆地标记为 0。
统计剩余陆地
- 遍历整个矩阵,统计值仍为 1 的格子数量,即为飞地数量。
代码实现
cpp
class Solution {
public:
typedef pair<int, int> PII;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
int numEnclaves(vector<vector<int>>& grid) {
int n = grid.size();
int m = grid[0].size();
queue<PII> q;
for (int i = 0; i < n; i++) {
if (grid[i][0] == 1) {
q.push({i, 0});
grid[i][0] = 0;
}
if (grid[i][m - 1] == 1) {
q.push({i, m - 1});
grid[i][m - 1] = 0;
}
}
for (int i = 0; i < m; i++) {
if (grid[0][i] == 1) {
q.push({0, i});
grid[0][i] = 0;
}
if (grid[n - 1][i] == 1) {
q.push({n - 1, i});
grid[n - 1][i] = 0;
}
}
while (q.size() > 0) {
int sz = q.size();
while (sz--) {
auto [a, b] = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int x = a + dx[i];
int y = b + dy[i];
if (x >= 0 && x < n && y >= 0 && y < m && grid[x][y] == 1) {
q.push({x, y});
grid[x][y] = 0;
}
}
}
}
int ret = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == 1)
ret++;
}
}
return ret;
}
};
三、地图中的最高点
题目解析

这道题是要根据给定的m×n整数矩阵isWater(0 表示陆地、1 表示水域),给每个格子安排非负高度,满足:水域高度必须为 0;相邻格子(正东、南、西、北方向)高度差至多为 1。最终要找出使矩阵最高高度最大的高度安排方案,返回对应的高度矩阵height。
算法思路
对于这道题,就不能像上面那样一次一次进行BFS遍历能解决了;
这里就只能同时从多个0位置开始遍历,让相邻格子的高度比当前位置高度大1。
- 水域是高度起点(0),陆地高度由「离最近水域的距离」决定(距离越远高度越高,且满足相邻差≤1)。
- 多源 BFS:所有水域同时入队,按层级扩散(同一层级高度相同),确保每个格子首次被访问时的高度是最小可行高度,最终整体最高。
多源BFS:
- 初始化:高度矩阵 high 全设为 - 1(未赋值),遍历矩阵,将所有水域坐标设为 0 并加入队列。
- BFS 遍历:出队当前格子,遍历 4 个相邻方向,若相邻格子是未赋值的陆地(high==-1),则其高度设为当前格子高度 + 1,入队继续扩散。
- 返回高度矩阵 high。
代码实现
cpp
class Solution {
public:
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
typedef pair<int, int> PII;
vector<vector<int>> highestPeak(vector<vector<int>>& isWater) {
int n = isWater.size();
int m = isWater[0].size();
queue<PII> q;
vector<vector<int>> high(n, vector<int>(m, -1));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (isWater[i][j] == 1) {
high[i][j] = 0;
q.push({i, j});
}
}
}
while (q.size() > 0) {
int sz = q.size();
while (sz--) {
auto [a, b] = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int x = a + dx[i];
int y = b + dy[i];
if (x >= 0 && x < n && y >= 0 && y < m &&
high[x][y] == -1) {
high[x][y] = high[a][b] + 1;
q.push({x, y});
}
}
}
}
return high;
}
};
四、地图分析
题目解析

这道题是要在 n×n 的网格 grid 中(0 代表海洋,1 代表陆地),找出一个海洋单元格,使得它到离它最近的陆地单元格的曼哈顿距离最大,返回这个最大距离。如果网格只有陆地或只有海洋,返回 -1。
算法思路
对于这道题,就要从所有的1陆地,进行多源BFS遍历。
- 所有陆地同时作为 BFS 起点(多源),按层级扩散(每一层对应距离 + 1),确保海洋首次被访问时的距离是 "最近陆地距离"。
- 扩散过程中直接修改原网格(海洋置 1),避免额外访问标记数组。
多源BFS
- 初始化:遍历网格,所有陆地(1)入队;若全是陆地 / 全是海洋,直接返回 - 1。
- BFS 层级遍历:每轮扩散前距离 + 1(初始 - 1,首轮扩散后为 0,对应陆地相邻海洋的距离),遍历当前队列中所有陆地的 4 个相邻方向。
- 若相邻是海洋(0),标记为 1(已访问)并入队,继续扩散。
- 遍历结束后,返回最终累计的距离(即最大最近距离)。
代码实现
cpp
class Solution {
public:
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
typedef pair<int, int> PII;
int maxDistance(vector<vector<int>>& grid) {
int n = grid.size();
int m = grid[0].size();
queue<PII> q;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == 1)
q.push({i, j});
}
}
if(q.empty() || q.size() == n*m)
return -1;
int ret = -1;
while (q.size() > 0) {
ret++;
int sz = q.size();
while (sz--) {
auto [a, b] = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int x = a + dx[i];
int y = b + dy[i];
if (x >= 0 && x < n && y >= 0 && y < m && grid[x][y] == 0) {
grid[x][y] = 1;
q.push({x, y});
}
}
}
}
return ret;
}
};
本篇文章到这里就结束了,感谢支持
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws