多源广度优先搜索(LeetCode542. 01矩阵)

LeetCode542. 01矩阵

广度优先搜索

对于矩阵中的每一个元素,如果它的值为 0,那么离它最近的 0就是它自己。如果它的值为1,那么我们就需要找出离它最近的 0,并且返回这个距离值。那么我们如何对于矩阵中的每一个1,都快速地找到离它最近的 0呢?

如果矩阵中只有一个0,那么我们可以直接使用DFS深搜递归,或者单源的BFS广搜队列,找完整个矩阵,更新距离即为最终答案

如图:
初始状态:
_ _ _ _
_ 0 _ _
_ _ _ _
_ _ _ _
其中只有一个 0,剩余的 1我们用短横线表示。如果我们从0 开始进行广度优先搜索,那么结果依次为:
多源广度优先搜索(LeetCode542. 01矩阵)_第1张图片
也就是说,在广度优先搜索的每一步中,如果我们从矩阵中的位置 x x x 搜索到了位置 y y y,并且 y y y 还没有被搜索过,那么位置 y y y0的距离就等于位置 x x x0 的距离加上 1

如果有多个0

处理的方法很简单:我们在进行广度优先搜索的时候会使用到队列,在只有一个 0 的时候,我们在搜索前会把这个 0 的位置加入队列,才能开始进行搜索;如果有多个 0,我们只需要把这些 0 的位置都加入队列就行了。
我们还是举一个例子,在这个例子中,有两个 0

在这里插入图片描述
按照单源0的方法广搜四个方向:
多源广度优先搜索(LeetCode542. 01矩阵)_第2张图片
把更新过的加入广搜队列,重复操作:
多源广度优先搜索(LeetCode542. 01矩阵)_第3张图片

这样做为什么是正确的呢?

  • 我们需要对于每一个1 找到离它最近的0。如果只有一个0的话,我们从这个 0开始广度优先搜索就可以完成任务了;

  • 但在实际的题目中,我们会有不止一个0。我们会想,要是我们可以把这些 0看成一个整体好了。有了这样的想法,我们可以添加一个「超级零」,它与矩阵中所有的 0 相连,这样的话,任意一个 1 到它最近的0 的距离,会等于这个1「超级零」的距离减去一。由于我们只有一个「超级零」,我们就以它为起点进行广度优先搜索。这个「超级零」只和矩阵中的0相连,所以在广度优先搜索的第一步中,「超级零」会被弹出队列,而所有的 0会被加入队列,它们到「超级零」的距离为1。这就等价于:一开始我们就将所有的 0加入队列,它们的初始距离为 0。这样以来,在广度优先搜索的过程中,我们每遇到一个1,就得到了它到「超级零」的距离减去一,也就是 这个 1到最近的 0的距离。

代码(c++)–可作为矩阵多源广搜板子

class Solution {
private:
    static constexpr int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
        int m = matrix.size(), n = matrix[0].size();
        vector<vector<int>> dist(m, vector<int>(n));
        vector<vector<int>> seen(m, vector<int>(n));//访问标志
        queue<pair<int, int>> q;
        // 将所有的 0 添加进初始队列中
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (matrix[i][j] == 0) {//多源进队(板子修改处)
                    q.emplace(i, j);
                    seen[i][j] = 1;
                }
            }
        }

        // 广度优先搜索
        while (!q.empty()) {
            auto [i, j] = q.front();
            q.pop();
            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]) {//根据题意维护矩阵(板子修改处)
                    dist[ni][nj] = dist[i][j] + 1;
                    q.emplace(ni, nj);
                    seen[ni][nj] = 1;
                }
            }
        }

        return dist;
    }
};


多源广度搜索的另一题应用:LeetCode994
内容来自LeetCode官方题解,博主稍作修改批注

觉得文章有用,点个赞,点个收藏,支持一下

你可能感兴趣的:(算法,算法,数据结构,leetcode,c++)