LeetCode 评论区:你管这难度叫简单???

点击上方“五分钟学算法”,选择“星标”公众号

重磅干货,第一时间送达

大家好,我是吴师兄。

今天分享的题目来源于 LeetCode 第 994 号问题,在早期标记简单题目,但经过评论区的愤怒讨伐,调整为中等。

题目描述:

在给定的网格中,每个单元格可以有以下三个值之一:
 值0代表空单元格;
 值1代表新鲜橘子;
 值2代表腐烂的橘子。
每分钟,任何与腐烂的橘子(在4个正方向上)相邻的新鲜橘子都会腐烂。返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回-1。
示例1:
 输入:[[2,1,1],[1,1,0],[0,1,1]]
 输出:4
示例2:
 输入:[[2,1,1],[0,1,1],[1,0,1]]
 输出:-1
 解释:左下角的橘子(第2行,第0列)永远不会腐烂,因为腐烂只会发生在4个正向上。

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

提示:
 1<=grid.length<=10
 1<=grid[0].length<=10
 grid[i][j]仅为0、1或2

由题意:只有腐烂的橘子才可以去污染它周围四个方向上存在的新鲜橘子,且它每一分钟只能污染一次,下一次,被它腐蚀的橘子再去腐蚀自己周边的新鲜橘子,每次只有被新腐蚀的橘子才能继续向外腐蚀(因为旧的腐烂的橘子已经被“包围”了)

这就很像一个人得了传染病,只要他遇见人就会将病传染给那个人,而被传染的又会去感染别的人(不同的是,这里的橘子的位置是固定的,无法移动)

思路是非常简单的,我们通过动态图直观理解下:

腐烂的橘子gif演示

既然理清了思路,那么我们来试试代码:首先,我们需要知道初始状态下的单元格中有多少腐烂的橘子,并且要将它们的位置信息保存下来,我们可以用一个队列(先入先出)将(x,y)保存下来;然后我们开始遍历整个队列,每次弹出一个保存的位置信息,将这个位置周围的新鲜橘子全部腐蚀,然后把该位置的信息从队列中删除(旧的信息在下次腐蚀中已经没用了),并且将被腐蚀的橘子的位置信息存入队列中,在下次循环中从它们的位置上再“向外延伸”;直到队列为空,循环结束,这个时候并不能说明整个单元格中已经不存在新鲜的橘子,因为可能存在下面这种情况:

很明显,标红的区域(新鲜橘子)永远不能被腐蚀,因为它周围唯一的两个单元格是空的。

那么针对这种情况,我们在前面遍历统计腐烂橘子的时候可以顺便统计一下新鲜橘子的数量count,后面我们每腐蚀一个橘子就从count中减去1。最终循环结束的时候,我们只需要判断count是否大于0,若是,返回-1,否则返回轮数res。


代码:

public static int orangesRotting02(int[][] grid){
    int row = grid.length,col = grid[0].length;
    Queue<int[]> queue = new ArrayDeque();
    int count = 0;//统计新鲜橘子的数量
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            if (grid[i][j] == 2) {
                queue.add(new int[]{i,j});
            }
            if (grid[i][j] == 1) {
                count++;
            }
        }
    }
    int res = 0;
    while (count > 0 && !queue.isEmpty()) {
        res++;
        int size = queue.size();
        for (int i = 0; i < size; i++) {
            int[] temp = queue.poll();
            int r = temp[0],c = temp[1];//(x,y)
            //上
            if (r > 0 && grid[r-1][c] == 1) {
                grid[r-1][c] = 2;
                count--;
                queue.add(new int[]{r-1,c});
            }
            //下
            if (r < grid.length-1 && grid[r+1][c] == 1) {
                grid[r+1][c] = 2;
                count--;
                queue.add(new int[]{r+1,c});
            }
            //左
            if (c > 0 && grid[r][c-1] == 1) {
                grid[r][c-1] = 2;
                count--;
                queue.add(new int[]{r,c-1});
            }
            //右
            if (c < grid[0].length-1 && grid[r][c+1] == 1) {
                grid[r][c+1] = 2;
                count--;
                queue.add(new int[]{r,c+1});
            }
        }
    }
    if (count > 0) {
        return -1;
    }
    return res;
}

执行用时:3 ms, 在所有 Java 提交中击败了85.33% 的用户
内存消耗:37.6 MB, 在所有 Java 提交中击败了98.26% 的用户


推荐阅读

•   吴师兄实名吐槽 LeetCode 上的一道题目。。。•   面试字节跳动时,我竟然遇到了原题……•   计算机专业的学生怎样练习编程才能把编程学精通?•   为什么 MySQL 使用 B+ 树•   一道简简单单的字节跳动算法面试题


欢迎关注我的公众号“五分钟学算法”,如果喜欢,麻烦点一下“在看”,点击左下方阅读原文,获取谷歌师兄的算法刷题笔记。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值