994.腐烂的橘子

994.腐烂的橘子

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

值 0 代表空单元格;
值 1 代表新鲜橘子;
值 2 代表腐烂的橘子。
每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。

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

示例 1:

994.腐烂的橘子

输入:grid = [[2,1,1],[1,1,0],[0,1,1]]
输出:4
示例 2:

输入:grid = [[2,1,1],[0,1,1],[1,0,1]]
输出:-1
解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个正向上。
示例 3:

输入:grid = [[0,2]]
输出:0
解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。

为什么用BFS
由题目可知每过一分钟腐烂的橘子周围的新鲜橘子也会腐烂掉,我们需要返回给定网格中的橘子多久会全部腐烂,如果不能全部腐烂则返回1,这种网格问题一开始肯定会想到DFS,即深度优先遍历,但是仔细想想,每个腐烂橘子每分钟都会腐烂周围的橘子,我们对一个腐烂橘子深度搜索没有任何意义,所以思路转变为BFS,即广度优先搜索,有了这一层想法后思路也很简单了,通常BFS应用在树结构上,用来求最短路径。

何为广度优先搜索
官解:所谓广度优先搜索,就是从起点出发,每次都尝试访问同一层的节点,如果同一层都访问完了,再访问下一层,最后广度优先搜索找到的路径就是从起点开始的最短合法路径。
通俗地讲:BFS 可以看成是层序遍历。从某个结点出发,BFS 首先遍历到距离为 1 的结点,然后是距离为 2、3、4…… 的结点。因此,BFS 可以用来求最短路径问题。BFS 先搜索到的结点,一定是距离最近的结点。

BFS思路
对于本题目,每分钟腐烂的橘子都会感染周围的新鲜橘子,被感染的橘子再过一分钟又会感染周围新鲜橘子,直到感染所以可以感染到的新鲜橘子,这过程就很像BFS嘛,实际上这道题在我眼里也是一个求最短路径的模型,腐烂橘子到所有新鲜橘子的最短路径,路径的长度就是最后的时间。
对于树我们可以从根节点开始逐层遍历,如果本题初始状态只有一个腐烂橘子的话也一样,但是可能有多个腐烂橘子,所以我们要用多源BFS,也很简单,先遍历一遍数组记录每个初始状态的腐烂橘子。

一般BFS都是通过队列实现的,把最开始的腐烂橘子的下标储存在一个队列中,然后逐个出队找腐烂橘子周围的新鲜橘子,感染它并且将它入队,用来感染下一层橘子,因为题目要求路径,所以我们需要通过一个变量来保存每一层入队的被感染橘子的数量,在遍历完一层后结果要加一,当腐烂橘子周围再也没有新鲜橘子时退出循环,然后再次遍历网格,如果还有新鲜橘子则返回-1,没有的话返回结果。

细节处理
这里有一个细节int res = -1;和return res == -1 ? 0 : res;,为什么结果初始化为-1呢,因为最开始所有腐烂橘子入队时res也要加一,如果没有新鲜橘子的话返回0,但是初始化化为0的话就会返回1,这不合理。对于初始化可以这么理解,最开始有一个超级细菌,在0时刻感染了最开始腐烂的橘子,我们要求的是这些橘子感染其他橘子的时间,所以初始化结果为-1了。但是还有一种情况是网格里一个腐烂橘子都没有,这样的话根本就不会进入循环,最后返回-1也不合理,所以当最后结果为-1时返回0即可,如何解释呢,如果超级细菌最开始没有感染橘子,那么0时刻(开始感染的时刻)和-1时刻(所有橘子都是新鲜的)将没有任何区别,但是时间依然流动了。
完整代码如下:
Ps:还可以优化,在这基础上加一个变量保存新鲜橘子的数量,就不需要最后再遍历一次数组了,只需要判断该变量是否为0即可。

class Solution {
    public int orangesRotting(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        Deque<int[]> queue = new LinkedList<>();  //队列实现BFS
        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});  //将最开始的腐烂橘子入队
                }
            }
        }
        int res = -1;
        while (!queue.isEmpty()) {  //还有可以被感染的橘子时循环
            int q = queue.size();  //该变量保存每一层橘子的个数
            res++;  //走完一层就+1
            for (int i = 0; i < q; i++) {  //循环遍历一层
                int[] temp = queue.poll();
                int r = temp[0];
                int c = temp[1];
                if (r - 1 >= 0 && grid[r - 1][c] == 1) {  //访问上边,如果不越界且为新鲜橘子则入队并且感染
                    queue.offer(new int[]{r - 1, c});
                    grid[r - 1][c] = 2;
                }
                if (r + 1 < m && grid[r + 1][c] == 1) {  //
                    queue.offer(new int[]{r + 1, c});
                    grid[r + 1][c] = 2;
                }
                if (c - 1 >= 0 && grid[r][c - 1] == 1) {  //
                    queue.offer(new int[]{r, c - 1});
                    grid[r][c - 1] = 2;
                }
                if (c + 1 < n && grid[r][c + 1] == 1) {  //
                    queue.offer(new int[]{r, c + 1});
                    grid[r][c + 1] = 2;
                }
            }
        }
        for (int i = 0; i < m; i++) {  //遍历最后的结果
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {  //如果还有新鲜橘子返回-1
                    return -1;
                }
            }
        }
        return res == -1 ? 0 : res;  //如果一开始没有腐烂橘子返回0,否则返回结果
    }
}

原文:https://leetcode.cn/problems/rotting-oranges/solution/by-nice-hermann9a2-tdws/

Original: https://www.cnblogs.com/liangren-na/p/16437624.html
Author: 良人呐
Title: 994.腐烂的橘子

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/619861/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • SQL的多表查询

    显示内连接: select 字段列表 from 表1 [inner] join 表2 on 连接条件; (PS:方括号(“[]”)内的为可选项;) (注意:…

    数据库 2023年5月24日
    0108
  • 排查线上问题的9种方式

    德国科技管理专家斯坦门茨早年移居美国,他以非凡的才能成为美国企业界的佼佼者。一次,美国著名的福特公司的一组电机发生故障,在束手无策之时,公司请斯坦门茨出马解决问题。 斯坦门茨在电机…

    数据库 2023年6月6日
    081
  • CronExpression使用笔记

    CronExpression一般是使用在自动任务中,可以指定任务执行的时间或者时间规律,下面记录一下表达试的使用说明 CronExpression由7个子表达式组成,7个子表达式之…

    数据库 2023年6月9日
    0102
  • http状态码总结

    表示临时响应并需要请求者继续执行操作的状态代码。 100 (继续) 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。101 (切换协议) 请求…

    数据库 2023年6月6日
    063
  • 【中国信通院 x ShardingSphere 金融用户社区】成立,多家知名金融机构正式入驻

    2022 年 5 月 20 日”OSCAR 开源先锋日”现场,Apache ShardingSphere 联合中国信通院共同成立了【中国信通院 x Shar…

    数据库 2023年6月16日
    088
  • 4、异常

    一、异常的体系结构: java.lang.Throwable |—–java.lang.Error:一般不编写针对性的代码进行处理。 |—&#8…

    数据库 2023年6月6日
    093
  • java中如何打印出一个类中所有变量呢?

    下文笔者将讲述,使用java代码打印出一个类中所有变量的方法分享,如下所示: 在日常开发中,我们经常需获取一个类的变量信息,然后操作变量,那么该如何编写此类代码呢?当然我们可以借助…

    数据库 2023年6月11日
    073
  • haproxy

    haproxy 一.haproxy简介 二.负载均衡 三.haproxy安装 1.yum安装 2.源码安装 2.1 配置文件解析 2.2时间格式 2.3 全局global 2.4 …

    数据库 2023年6月14日
    073
  • 17、是否可以继承 String 类

    String类是final类,不可以被继承。 posted @2020-12-22 15:50 卫盾 阅读(111 ) 评论() 编辑 Original: https://www….

    数据库 2023年6月6日
    099
  • 【转】MySQL合理使用索引

    索引可以说是数据库中的一个大心脏了,如果说一个数据库少了索引,那么数据库本身存在的意义就不大了,和普通的文件没什么两样。所以说一个好的索引对数据库系统尤其重要,今天来说说MySQL…

    数据库 2023年5月24日
    083
  • 程序里随处可见的interface,真的有用吗?真的用对了吗?

    这两天在和一小伙伴研究解决RabbitMQ集群重启慢导致Consumer自动重连超时的问题,已经有了解决方案。接下来需要做个整理。由于同时涉及到springboot自动配置、spr…

    数据库 2023年6月9日
    0101
  • RabbitMQ的延迟消息(或预定消息)添加到 RabbitMQ 的插件

    1.插件网站下载自己的版本插件,,以rabbitmq_delayed_message_exchange-3.10.0.ez .ez为后缀 https://github.com/ra…

    数据库 2023年6月6日
    0105
  • MySQL之连接查询和子查询

    多表连接的基本语法 多表连接,即将多个表拼接成一个表,然后进行查询 [En] Multi-table join, that is, several tables are splic…

    数据库 2023年5月24日
    0140
  • 剑指 Offer II 091. 粉刷房子

    剑指 Offer II 091. 粉刷房子 动态规划当前粉刷房子的花费可以由上一家粉刷房子的花费推导出来,所以可以使用动态规划求解这道题。首先确定dp数组的含义,每个房子都可以被粉…

    数据库 2023年6月16日
    099
  • gitlab-runner浅谈——【git fetch-pack: expected shallow list】解决方法

    配置完gitlab-runner后执行job总是失败,如下: 解决方法 分析原因发现是git的版本太低了,我用的是系统自带的1.8.3的版本。后来更新为:2.31.1 后job可以…

    数据库 2023年6月11日
    079
  • MySQL&MariaDB数据库备份脚本

    MySQL&MariaDB数据库备份脚本 MySQL&MariaDB数据库备份脚本 MySQL & MariaDB .bat backup.sh MySQL…

    数据库 2023年6月9日
    078
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球