一.题目

二.思路讲解
2.1 多源最短路径是什么
多源最短路径 是在单源最短路径 的基础上,将多个起点同时加入队列进行 BFS。
-
单源:从单一源点出发,BFS 逐层扩散,计算到所有点的最短距离。
-
多源 :将所有源点初始时一并入队 ,同时开始向外层扩散,每个点被第一次访问时的距离就是离最近的源点的距离。
2.2 思路讲解
本题要求矩阵中每个 1 到最近 0 的距离。如果按照这个思路,首先你需要找到最近的0,然后把距离填回来,但是如果是0就不需要填回来,因此采用正难则反策略:
-
将所有
0作为多源起点 同时入队,距离初始为0。 -
然后进行 BFS,每层向外扩展一步,对于新到达的格子,其距离 = 当前格子距离 + 1。
-
由于 BFS 按层扩散,第一次访问到某个格子时,记录的距离就是最近的 0 的距离。
-
无需像单源 BFS 那样记录每层大小(
sz),只需在扩展时直接使用当前格子的距离加 1 赋值给邻居即可。
三.代码演示
cpp
class Solution {
public:
int bx[4] = {0,0,-1,1};
int by[4] = {1,-1,0,0};
typedef pair<int,int> PII;
vector<vector<int>> updateMatrix(vector<vector<int>>& mat)
{
int row = mat.size(),col = mat[0].size();
//dist[i][j] == -1 表示:没有搜索过
//dist[i][j] != -1 表示:最短距离
vector<vector<int>> dist(row,vector<int>(col,-1));
queue<PII>q;
//1.把所有源点都放入队列中
for(int i = 0;i < row;i++)
{
for(int j = 0;j < col;j++)
{
if(mat[i][j] == 0)
{
q.push({i,j});
dist[i][j] = 0;
}
}
}
//2.处理队列
while(q.size())
{
auto [a,b] = q.front();
q.pop();
for(int k = 0;k < 4;k++)
{
int x = a + bx[k],y = b + by[k];
if(x >= 0 && y >= 0 && x < row && y < col && dist[x][y] == -1)
{
dist[x][y] = dist[a][b] + 1;
q.push({x,y});
}
}
}
return dist;
}
};
四.代码讲解
一、初始化距离数组与队列
-
dist:二维整型数组,大小与mat相同,初始化为 -1 ,表示该格子尚未被访问。最终dist[i][j]将存储从格子(i, j)到最近 0 的曼哈顿距离。 -
队列
q:存储待扩展的格子坐标,用于 BFS 逐层扩散。
二、多源起点入队
遍历整个矩阵,将所有值为 0 的格子坐标入队,并将 dist 中对应位置设为 0 。这些 0 格子就是 BFS 的多源起点,同时作为距离计算的基准。
三、BFS 逐层扩展
当队列非空时,循环执行以下操作:
-
取出队头坐标
(a, b)。 -
遍历四个方向,计算新坐标
(x, y)。 -
若新坐标在网格内且
dist[x][y] == -1(即未被访问),则:-
设置
dist[x][y] = dist[a][b] + 1,表示从最近的 0 到达该格子的最短步数。 -
将
(x, y)入队,继续向外扩展。
-
四、关键细节
-
多源 BFS 的核心 :将所有源点同时入队,它们会在同一层开始扩散,保证每个格子找到的是离它最近的源点的距离。
-
距离数组的初始化 :用 -1 表示未访问,0 表示源点本身,后续通过
dist[a][b] + 1递推,避免额外标记数组。 -
无需按层处理 :由于距离值已经隐含了层次信息(每扩展一步距离加 1),直接使用
dist数组即可,不需要单独记录step和sz。
五、流程图
