542. 01 矩阵、1162. 地图分析、994. 腐烂的橘子

本次的三道题都用了多源点BFS的方法,关于什么是多源点BFS呢,就是求很多个起点到一个终点的关系,就将终点入队,反过来求。如下面三道题:

542. 01 矩阵

给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。

两个相邻元素间的距离为 1 。

示例 1:


输入:mat = [[0,0,0],[0,1,0],[0,0,0]]
输出:[[0,0,0],[0,1,0],[0,0,0]]

示例 2:


输入:mat = [[0,0,0],[0,1,0],[1,1,1]]
输出:[[0,0,0],[0,1,0],[1,2,1]]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/01-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路及方法

这道题要求的是每一个1离最近0的距离,那么可以假设这个矩阵就只有一个0,其余的都是1,就是多源点BFS问题,所以就将所有的0入队,然后开始用BFS来计算。

用一个新的dist矩阵来记录每一个1距离最近的0的距离。

class Solution {
    // 方向
    static int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    public int[][] updateMatrix(int[][] mat) {
        int m = mat.length,n = mat[0].length;
        // 记录已访问的节点
        boolean[][] visited = new boolean[m][n];
        // 初始队列
        Queue<int[]> queue = new LinkedList<>();
        for (int i = 0; i < mat.length; i++) {
            for (int j = 0; j < mat[0].length; j++) {
                // 所有0全部入队
                if (mat[i][j] == 0) {
                    queue.offer(new int[]{i, j});
                    visited[i][j] = true;
                }
            }
        }

        // 记录距离
        int[][] dist = new int[m][n];
        // 搜索0位置的四周,并记录距离
        while (!queue.isEmpty()) {
            int[] cur = queue.poll();
            int row = cur[0], cln = cur[1];
            for (int i = 0; i < 4; i++) {
                int ni = row + dirs[i][0];
                int nj = cln + dirs[i][1];
                if (ni >= 0 && nj >= 0 && ni < m &&  nj < n && !visited[ni][nj]) {
                    dist[ni][nj] = dist[row][cln] + 1;
                    queue.offer(new int[]{ni, nj});
                    visited[ni][nj] = true;
                }
            }
        }

        return dist;
    }
}

结果如下:

1162. 地图分析

你现在手里有一份大小为 N x N 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地,请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的。

我们这里说的距离是「曼哈顿距离」( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1| 。

如果网格上只有陆地或者海洋,请返回 -1。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/as-far-from-land-as-possible
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路及方法

这道题跟上面是同样的方法,只不过是找到0距离最近的1的距离,所以就将所有的1入队,然后进行BFS算法。

注意需要判断全1或者全0的情况,就只用判断队列的长度是否为m*n或者0。

class Solution {
    // 方向
    static int[][] dirs = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    public int maxDistance(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        // 初始队列
        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});
                } else {
                    grid[i][j] = -1;
                }
            }
        }
        // 如果全为陆地或嗨哟
        if (queue.size() == m * n || queue.size() == 0) return -1;
        // BFS
        while (!queue.isEmpty()) {
            int[] cur = queue.poll();
            int row = cur[0], cln = cur[1];
            for (int i = 0; i < 4; i++) {
                int newRow = row + dirs[i][0];
                int newCln = cln + dirs[i][1];
                if (newRow < 0 || newCln < 0 || newRow >= m || newCln >= n || grid[newRow][newCln] > 0) continue;
                grid[newRow][newCln] = grid[row][cln] + 1;
                // 周围节点入队
                queue.offer(new int[]{newRow, newCln});
            }
        }

        int maxDist = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                maxDist = Math.max(maxDist, grid[i][j]);
            }
        }

        return maxDist - 1;
    }
}

结果如下:

994. 腐烂的橘子

在给定的网格中,每个单元格可以有以下三个值之一:

值 0 代表空单元格;
值 1 代表新鲜橘子;
值 2 代表腐烂的橘子。
每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。

返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rotting-oranges
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路及方法

一样的思想,腐烂的橘子先入队,然后影响周围的橘子。

需要判断的是没有橘子,即全0的情况,就用一个参数计数。

class Solution {
    public static int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

    public int orangesRotting(int[][] grid) {
        int m = grid.length, n = grid[0].length;

        int countZero = 0;
        // 初始队列
        Queue<int[]> queue = new LinkedList<>();
        // 所有腐烂橘子入队
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 2) {
                    queue.offer(new int[]{i, j});
                }
                // 考虑0的情况
                if (grid[i][j] == 0) {
                    countZero++;
                }
            }
        }
        // 如果没有橘子
        if (countZero == m * n) return 0;

        int time = 0;
        // BFS将所有腐烂橘子四周的橘子腐烂
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int[] cur = queue.poll();
                int row = cur[0], cln = cur[1];
                // 四周橘子腐烂
                for (int j = 0; j < 4; j++) {
                    int newRow = row + dirs[j][0];
                    int newCln = cln + dirs[j][1];
                    // 出界或者周围不是新鲜橘子,continue
                    if (newRow < 0 || newCln < 0 || newRow >= m || newCln >= n || grid[newRow][newCln] != 1) continue;
                    grid[newRow][newCln] = 2;
                    queue.offer(new int[]{newRow, newCln});
                }
            }
            // 更新时间
            time++;
        }

        // 判断是否还有新鲜橘子
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) return -1;
            }
        }
        
        return time - 1;
    }
}

结果如下:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容