【广度优先搜索】多源BFS:矩阵,飞地的数量,地图中的最高点,地图分析

文章目录

多源BFS

解决多个源头的权值为1的最短路径问题。

  1. 暴力解法:细化为多个单源BFS,取最小值,大概率会超时。
  2. 把所有源点看作一个"超级源点",问题就变成了单源最短路径问题。只需要从超级源点开始进行一次BFS就可以得到结果
    • 把所有起点加入到队列里,开始BFS搜索

1. 01矩阵(LC 542)

01矩阵

题目描述

解题思路

如果把1当作起点,找到0以后还要回退到源点,比较复杂;正难则反,把0当作起点,到达终点后可以直接记录步数。

代码实现

java 复制代码
class Solution {
    public int[][] updateMatrix(int[][] mat) {
        Queue<int[]> queue = new LinkedList<>();
        int m = mat.length;
        int n = mat[0].length;
        int[][] ret = new int[m][n];
        int[] dx = { 0, 0, 1, -1 };
        int[] dy = { 1, -1, 0, 0 };

        //初始化为-1,标记当前位置没有被搜索过
        for (int[] arr : ret)
            Arrays.fill(arr, -1);

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (mat[i][j] == 0) {
                    ret[i][j] = 0;
                    queue.offer(new int[] { i, j });
                }
            }
        }

        //这里不需要求队列大小,也不需要step统计,直接在原来的基础上+1就是新的步数
        while (!queue.isEmpty()) {
            int[] top = queue.poll();
            int ii = top[0];
            int jj = top[1];
            for (int k = 0; k < 4; k++) {
                int x = dx[k] + ii;
                int y = dy[k] + jj;
                if (x >= 0 && x < m && y >= 0 && y < n && ret[x][y] == -1){
                    queue.offer(new int[]{x,y});
                    ret[x][y] = ret[ii][jj]+1;
                }
            }
        }
        return ret;
    }
}

2. 飞地的数量(LC 1020)

飞地的数量

题目描述

解题思路

正难则反,直接从边界开始向内搜索,所有被遍历到的1都是可以移动出去的;再依次遍历数组,BFS中未被遍历的1就是答案。

代码实现

java 复制代码
class Solution {
    public int numEnclaves(int[][] grid) {
        int[] dx = {0,0,1,-1};
        int[] dy = {1,-1,0,0};
        int m = grid.length;
        int n = grid[0].length;
        boolean[][] vis = new boolean[m][n];

        Queue<int[]> queue = new LinkedList();
        int ret = 0;

        //检索边缘1
        for(int i = 0;i<m;i++){
            if(grid[i][0]==1){
                queue.offer(new int[]{i,0});
                vis[i][0] = true;
            }
            if(grid[i][n-1]==1){
                queue.offer(new int[]{i,n-1});
                vis[i][n-1] = true;
            }
        } 
        for(int j = 0;j<n;j++){
            if(grid[0][j]==1){
                queue.offer(new int[]{0,j});
                vis[0][j] = true;
            }
            if(grid[m-1][j]==1){
                queue.offer(new int[]{m-1,j});
                vis[m-1][j] = true;
            }
        } 

        //多源BFS
        while(!queue.isEmpty()){
            int[] top = queue.poll();
            int ii = top[0];
            int jj = top[1];
            for(int k = 0;k<4;k++){
                int x = ii+dx[k];
                int y = jj+dy[k];
                if(x>=0 && x<m && y>=0 && y<n && !vis[x][y] && grid[x][y] == 1){
                    vis[x][y] =true;
                    queue.offer(new int[] {x,y});
                }
            }
        }
        for(int i = 0;i<m ;i++){
            for(int j = 0;j<n;j++){
                if(!vis[i][j]  && grid[i][j] == 1)
                    ret++;
            }
        }
        return ret;
    }
}

3. 地图中的最高点(LC 1765)

地图中的最高点

题目描述

解题思路

从0开始,向周围逐步+1扩展

代码实现

java 复制代码
class Solution {
    public int[][] highestPeak(int[][] isWater) {
        int m = isWater.length;
        int n = isWater[0].length;
        int[] dx = {0,0,1,-1};
        int[] dy = {1,-1,0,0};
        int[][] ret = new int[m][n];

        for(int[] arr:ret)
            Arrays.fill(arr,-1);

        Queue<int[]> queue = new LinkedList<>();
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                if(isWater[i][j] == 1){
                    queue.offer(new int[]{i,j});
                    ret[i][j] = 0;
                }
            }
        }

        while(!queue.isEmpty()){
            int[] top = queue.poll();
            int ii = top[0];
            int jj = top[1];
            for(int k=0;k<4;k++){
                int x = ii +dx[k];
                int y = jj +dy[k];
                if(x>=0 && x<m && y >=0 && y<n && ret[x][y]==-1 && isWater[x][y]==0){
                    queue.offer(new int[]{x,y});
                    ret[x][y] = ret[ii][jj] +1;
                }
            }
        }
        return ret;
    }
}

4. 地图分析(LC 1162)

地图分析

题目描述

解题思路

从1开始多源BFS,利用数组记录距离。题中的曼哈顿距离与步长相等。

代码实现

java 复制代码
class Solution {
    public int maxDistance(int[][] grid) {
        int[] dx = {0,0,1,-1};
        int[] dy = {1,-1,0,0};
        int m = grid.length;
        int n = grid[0].length;
        int[][] dest = new int[m][n];

        for(int[] arr:dest)
            Arrays.fill(arr,-1);

        Queue<int[]> queue = new LinkedList<>();
        for(int i = 0;i<m;i++){
            for(int j = 0;j<n;j++){
                if(grid[i][j]==1){
                    queue.offer(new int[]{i,j});
                    dest[i][j] = 0;
                }
            }
        }

        int ret = -1;
        while(!queue.isEmpty()){
            int[] top = queue.poll();
            int a = top[0];
            int b = top[1];
            for(int k = 0;k<4;k++){
                int x = a+dx[k];
                int y = b+dy[k];
                if(x>=0 && x<m && y>=0 && y<n && dest[x][y]==-1 ){
                    dest[x][y] = dest[a][b] + 1;
                    queue.offer(new int[]{x,y});
                    ret = Math.max(ret,dest[x][y]);
                }
            }
        }
        return ret;
    }
}
相关推荐
JieE2121 天前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
JieE2122 天前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack202 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树2 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
JieE2123 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2123 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
vivo互联网技术3 天前
CVPR 2026 | 全新强化学习框架 BeautyGRPO:重塑真实人像
算法·大模型·cvpr·影像
Darling噜啦啦3 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
用户497863050733 天前
(一)小红的数组操作
算法·编程语言