题意描述:

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

  • 值 0 代表空单元格;
  • 值 1 代表新鲜橘子;
  • 值 2 代表腐烂的橘子。

每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。

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

提示:

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

示例:

一:

输入:[[2,1,1],[1,1,0],[0,1,1]]
输出:4

二:

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

三:

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

解题思路:

Alice: 这就是模拟题吗 ?
Bob: 可以当成模拟题去做。
Alice: 有点BFS的样子,用队列的话应该能减少重复计算的。
Bob: 对对。


代码:

Java 方法一: 模拟, 多次遍历二维数组。

class Solution {private int rotedCnt   = 0;private int orangeCnt  = 0;public int orangesRotting(int[][] grid) {// 统计共有多少橘子for(int i=0; i<grid.length; ++i){for(int j=0; j<grid[i].length; ++j){if(grid[i][j] > 0){orangeCnt += 1;}}}//System.out.println("oranges " + orangeCnt);// rotting(grid) 返回这一分钟有多少橘子会腐败int minutes = 0;while(rotting(grid) > 0){minutes ++;}//System.out.println("minutes " + minutes);//System.out.println("rotedCnt " + rotedCnt);// 腐败过程结束,查看结果if(rotedCnt == orangeCnt){return minutes;}else{return -1;}}public int rotting(int[][] grid){int rottingCnt = 0;rotedCnt       = 0;// 这一秒钟腐败的int[][] directions = {{1,0},{-1,0},{0,1},{0,-1}};for(int i=0; i<grid.length; ++i){for(int j=0; j<grid[i].length; ++j){if(grid[i][j] == 2){rotedCnt += 1;for(int[] direction : directions){int xx = i + direction[0];int yy = j + direction[1];if(xx >=0 && xx < grid.length && yy >= 0 && yy < grid[i].length && grid[xx][yy] == 1){grid[xx][yy] = 3;  // 把这一分钟要腐败的先标记为 3 防止与之前已经腐败的混淆rottingCnt ++;                  }}}}}for(int i=0; i<grid.length; ++i){for(int j=0; j<grid[i].length; ++j){if(grid[i][j] == 3){grid[i][j] = 2;}}}// 这一分钟的腐败过程结束,标记重置为2return rottingCnt;}
}

Python 方法一:

class Solution:def orangesRotting(self, grid: List[List[int]]) -> int:# 统计橘子总数self.orangeCnt = 0for row in grid:for cell in row:if cell > 0:self.orangeCnt += 1# 模拟腐烂过程self.rottedCnt = 0minute         = 0while self.helper(grid) > 0:minute += 1# 返回结果if self.orangeCnt == self.rottedCnt:return minuteelse:return -1 def helper(self, grid):self.rottedCnt = 0    # 置零,重新累加rotting        = 0    # 本次腐败的橘子数量 directions = [[1,0],[-1,0],[0,1],[0,-1]]for x in range(len(grid)):for y in range(len(grid[x])):if grid[x][y] == 2:self.rottedCnt += 1for direction in directions:xx = x + direction[0]yy = y + direction[1]if xx >= 0 and xx < len(grid) and yy >= 0 and yy < len(grid[xx]) and grid[xx][yy] == 1:grid[xx][yy]    = 3rotting        += 1for x in range(len(grid)):for y in range(len(grid[x])):if grid[x][y] == 3:grid[x][y] = 2return rotting

Python 方法二: 优化内存使用

class Solution:def orangesRotting(self, grid: List[List[int]]) -> int:self.orangeCnt = 0rotting        = []for x in range(len(grid)):for y in range(len(grid[x])):if grid[x][y] > 0:self.orangeCnt += 1if grid[x][y] == 2:rotting.append([x, y])self.rotted = 0minute      = 0rottingCnt, rotting = self.helper(grid, rotting)while rottingCnt > 0:minute += 1rottingCnt, rotting = self.helper(grid, rotting)if self.rotted == self.orangeCnt:return minuteelse:return -1def helper(self, grid, rotting):directions = [[1,0],[-1,0],[0,1],[0,-1]]rottingCnt = 0rottingOne = []for coor in rotting:self.rotted += 1for direction in directions:xx = coor[0] + direction[0]yy = coor[1] + direction[1]if xx>=0 and xx<len(grid) and yy>=0 and yy<len(grid[xx]) and grid[xx][yy] == 1:rottingCnt += 1grid[xx][yy] = 2rottingOne.append([xx, yy])return rottingCnt, rottingOne

javascript 方法一:一种啰嗦的写法,没有吧腐烂的过程抽象出来,反而用 flag 数组来标记最新腐烂的橘子。

var orangesRotting = function (grid) {// 获取新鲜的橘子(data[i][j] === 1 的)个数const getOrangeLeftCnt = (data) => {let orangeCnt = 0;for (let i = 0; i < data.length; ++i) {for (let j = 0; j < data[i].length; ++j) {orangeCnt += data[i][j] === 1 ? 1 : 0;}}return orangeCnt;};// 判断坐标是否合法, 是否没有越界const isLegalCoord = (x, y, data) => {return x >= 0 && x < data.length && y >= 0 && y < data[0].length;};const reset = (data) => {for (let i = 0; i < data.length; ++i) {for (let j = 0; j < data[i].length; ++j) {data[i][j] = 0;}}};const gridCopy = JSON.parse(JSON.stringify(grid));const flag = JSON.parse(JSON.stringify(grid));reset(flag);const directions = [[0, 1],[0, -1],[-1, 0],[1, 0],];let result = 0;let corrupt = 0;let newCorrupt = [];while (true) {corrupt = 0;for (let [xx, yy] of newCorrupt) {flag[xx][yy] = 0;}for (let i = 0; i < gridCopy.length; ++i) {for (let j = 0; j < gridCopy[i].length; ++j) {if (gridCopy[i][j] === 2 && flag[i][j] === 0) {// 烂橘子只能感染一次其他橘子flag[i][j] = 1;for (let dire of directions) {const xx = i + dire[0];const yy = j + dire[1];if (isLegalCoord(xx, yy, gridCopy) && gridCopy[xx][yy] === 1) {gridCopy[xx][yy] = 2;flag[xx][yy] = 1;newCorrupt.push([xx, yy]);corrupt += 1;}}}}}if (corrupt > 0) {result += 1;}if (corrupt === 0 || getOrangeLeftCnt(gridCopy) === 0) {break;}}result = getOrangeLeftCnt(gridCopy) === 0 ? result : -1;return result;
};

易错点:

  • 每一分钟只能 “BFS” 走一步,这一分钟即将腐烂的橘子不应该和上一分钟已经腐烂的橘子混淆,前者在这一分钟还不具备传播腐败的能力。

总结


LeetCode-994-腐烂的橘子相关推荐

  1. leetcode 994:腐烂的橘子 java

    994. 腐烂的橘子 - 力扣(LeetCode) (leetcode-cn.com) 多源广度优先搜索,初始的所有的腐烂橘子,等价于广度优先搜索的同一层,然后对每一层进行搜索: class Solu ...

  2. LeetCode 994. 腐烂的橘子

    994. 腐烂的橘子 思路:直接bfs会出现2个腐烂的橘子在两边同时进行,这样会错误. 正确思路:每分钟变化后所有橘子状态为next_grid,直到橘子状态不改变.如果状态不变,且无新鲜的橘子则返回时 ...

  3. 【广度优先搜索】leetcode 994. 腐烂的橘子

    994. 腐烂的橘子 文章目录 题目描述 示例1: 示例2: 示例3: 提示 方法:多源广度优先搜索 解题思路 代码 复杂度分析 题目描述 在给定的 m x n 网格 grid 中,每个单元格可以有以 ...

  4. LeetCode 994. 腐烂的橘子(图的BFS)

    1. 题目 在给定的网格中,每个单元格可以有以下三个值之一: 值 0 代表空单元格: 值 1 代表新鲜橘子: 值 2 代表腐烂的橘子. 每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会 ...

  5. leetcode 994 腐烂的橘子

    先给出题目: 在给定的网格中,每个单元格可以有以下三个值之一: 值 0 代表空单元格: 值 1 代表新鲜橘子: 值 2 代表腐烂的橘子. 每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都 ...

  6. leetcode 994.腐烂的橘子

    题目: 在给定的网格中,每个单元格可以有以下三个值之一: 值 0 代表空单元格: 值 1 代表新鲜橘子: 值 2 代表腐烂的橘子. 每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂 ...

  7. 图解LeetCode——994. 腐烂的橘子

    一.题目 在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一: 值 0 代表空单元格: 值 1 代表新鲜橘子: 值 2 代表腐烂的橘子. 每分钟,腐烂的橘子 周围 4 个方向上相 ...

  8. Leetcode 994. 腐烂的橘子(DAY 262)---- 后端面试题(2020.1.5 华为机试真题)

    文章目录 原题题目 代码实现(首刷自解 双百 挺简单的) 原题题目 代码实现(首刷自解 双百 挺简单的) class Solution {public:inline void get_badorang ...

  9. 994. 腐烂的橘子(Leetcode)(多源BFS)

    994. 腐烂的橘子 难度简单85 在给定的网格中,每个单元格可以有以下三个值之一: 值 0 代表空单元格: 值 1 代表新鲜橘子: 值 2 代表腐烂的橘子. 每分钟,任何与腐烂的橘子(在 4 个正方 ...

  10. 994. 腐烂的橘子

    994. 腐烂的橘子 在给定的网格中,每个单元格可以有以下三个值之一: 值 0 代表空单元格: 值 1 代表新鲜橘子: 值 2 代表腐烂的橘子. 每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新 ...

最新文章

  1. 文本框字符串长度实时统计jQuery插件,兼容IE6+
  2. mysql读取和写入的峰值_计算MySQL的内存峰值公式
  3. sql注入修复方法是_旧的方法是修复我们可以看到的内容。
  4. linux服务器管理公司用户,在Linux服务器Jenkins中管理用户和角色的方法
  5. 【树状数组】递增子序列(金牌导航 数据结构优化DP-1)
  6. 3-7:类与对象下篇——static成员
  7. Pull Request的正确打开方式(如何在GitHub上贡献开源项目)
  8. 微课|玩转Python轻松过二级:第3章课后习题解答4
  9. python列表相加的方法:两个list [] 加法
  10. html小游戏代码_厉害!84 行 JavaScript 代码实现塔式堆叠游戏
  11. python高维数据可视化_【机器学习】(十六)主成分分析PCA:高维数据可视化、特征提取...
  12. python 爬取生意参谋数据_如何爬取生意参谋数据?是不是违规操作?
  13. c语言编程实现合取析取,C++实现离散数学求主合取范式和主析取范式
  14. lastinsertid mysql_mysql - Go语言中文网 - Golang中文社区
  15. 读书笔记:《从生活常识的角度看懂财务报表》
  16. 我的VSTO之路(三):Word基本知识
  17. C#实现语音朗读功能
  18. java 基础:方法/函数
  19. 用Sendmail转寄信件
  20. background图片叠加_java实现图片的叠加效果

热门文章

  1. DAY 2 循环、随机数练习 - 年会抽奖程序京牌摇号小程序
  2. ERP,读《采购与供应链管理》
  3. 怎么把图片转成gif
  4. ImageJ 图片转GIF 视频转图片
  5. 国密SM9算法C++实现之四:基本功能函数与KGC接口的实现
  6. 三菱FX3U与3台三菱e740或D700变频器通讯程序
  7. 如何用python遍历文件夹下的所有excel文件
  8. CSS截图图片的几种方式
  9. 地球正在变“秃”?数据告诉你真相
  10. 淡雅创意不规则几何PPT模板