【广度优先搜索】多源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;
    }
}
相关推荐
状元岐13 分钟前
C#反射从入门到精通
java·javascript·算法
_深海凉_1 小时前
LeetCode热题100-除了自身以外数组的乘积
数据结构·算法·leetcode
Kk.08021 小时前
项目《基于Linux下的mybash命令解释器》(一)
前端·javascript·算法
xiaotao1312 小时前
01-编程基础与数学基石: Python核心数据结构完全指南
数据结构·人工智能·windows·python
SteveSenna2 小时前
Trossen Arm MuJoCo自定义1:改变目标物体
人工智能·学习·算法·机器人
yong99902 小时前
IHAOAVOA:天鹰优化算法与非洲秃鹫优化算法的混合算法(Matlab实现)
开发语言·算法·matlab
米粒13 小时前
力扣算法刷题 Day 42(股票问题总结)
算法·leetcode·职场和发展
浅念-5 小时前
从LeetCode入门位运算:常见技巧与实战题目全解析
数据结构·数据库·c++·笔记·算法·leetcode·牛客
CoovallyAIHub5 小时前
无人机拍叶片→AI找缺陷:CEA-DETR改进RT-DETR做风电叶片表面缺陷检测,mAP50达89.4%
算法·架构·github
CoovallyAIHub5 小时前
混合训练反而更差?VLM Agent在训练前协调跨数据集标注,文档布局检测F-score从0.860提升至0.883
算法·架构·github