【广度优先搜索】多源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;
    }
}
相关推荐
sali-tec2 小时前
C# 基于OpenCv的视觉工作流-章43-轮廓匹配
图像处理·人工智能·opencv·算法·计算机视觉
Coovally AI模型快速验证2 小时前
检测+跟踪一体化!4.39M参数、8.3W功耗,轻量化模型让无人机在露天矿实时巡检
算法·yolo·无人机·智能巡检·智慧矿山
玛卡巴卡ldf2 小时前
【LeetCode 手撕算法】(矩阵)73-矩阵置零、54-螺旋矩阵(贪吃蛇)、48-旋转图像
java·数据结构·算法·leetcode·力扣
C^h2 小时前
RTthread中的内存池理解
linux·数据库·c++·算法·嵌入式
深藏功yu名2 小时前
Day25(高阶篇):RAG检索与重排序算法精研|从原理到参数调优,彻底攻克检索瓶颈
人工智能·算法·ai·自然语言处理·排序算法·agent
郝学胜-神的一滴2 小时前
深入解析:生成器在UserList中的应用与Python可迭代对象实现原理
开发语言·python·程序人生·算法
雪木木2 小时前
刷题:力扣热题100--滑动窗口(Day03)
算法·leetcode
lcj25112 小时前
蓝桥杯C++:数据结构(功能导向速查)
数据结构·c++·蓝桥杯
Yzzz-F2 小时前
Problem - 2157D - Codeforces
算法