《LeetCode 542 01 矩阵 多源BFS解法》

一.题目

542. 01 矩阵 - 力扣(LeetCode)

二.思路讲解

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 逐层扩展

当队列非空时,循环执行以下操作:

  1. 取出队头坐标 (a, b)

  2. 遍历四个方向,计算新坐标 (x, y)

  3. 若新坐标在网格内且 dist[x][y] == -1(即未被访问),则:

    • 设置 dist[x][y] = dist[a][b] + 1,表示从最近的 0 到达该格子的最短步数。

    • (x, y) 入队,继续向外扩展。

四、关键细节
  • 多源 BFS 的核心 :将所有源点同时入队,它们会在同一层开始扩散,保证每个格子找到的是离它最近的源点的距离。

  • 距离数组的初始化 :用 -1 表示未访问,0 表示源点本身,后续通过 dist[a][b] + 1 递推,避免额外标记数组。

  • 无需按层处理 :由于距离值已经隐含了层次信息(每扩展一步距离加 1),直接使用 dist 数组即可,不需要单独记录 stepsz

五、流程图