leetcode 994 腐烂的橘子
程序员文章站
2022-05-21 12:08:29
...
先给出题目:
在给定的网格中,每个单元格可以有以下三个值之一:
值 0 代表空单元格;
值 1 代表新鲜橘子;
值 2 代表腐烂的橘子。
每分钟,任何与腐烂的橘子(在 4 个正方向上)相邻的新鲜橘子都会腐烂。
返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rotting-oranges
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
给出思路:
解题首要目的,先把问题解决,不论方法。首先考虑到,直接模拟腐烂的过程,最后统计腐烂的结果。考虑以下几种情况:一个网格里是腐烂的橘子,它只能腐化上下左右四个方向格子装有的新鲜橘子;如果腐烂的橘子周围没有新鲜的橘子,则无法传播腐化;当所有腐烂的橘子都无法传播腐化时,结束模拟过程,开始统计结果。
下面给出代码:
class Solution {
public int orangesRotting(int[][] grid) {
int count = 0;
while (true) {
if (haveNextStep(grid)) {
grid = rotting(grid);
count++;
} else {
if (isRotted(grid)) {
return count;
} else {
return -1;
}
}
}
}
//判断腐化能否继续进行下去
public Boolean haveNextStep(int[][] grid) {
int row = grid.length;
int col = grid[0].length;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if(grid[i][j] == 2 ) {
if (i - 1 >= 0 && grid[i - 1][j] == 1 ||
i + 1 < row && grid[i + 1][j] == 1 ||
j - 1 >= 0 && grid[i][j - 1] == 1||
j + 1 < col && grid[i][j + 1] == 1) {
return true;
}
}
}
}
return false;
}
//对结果进行判断,是否全部新鲜橘子被腐化
public Boolean isRotted(int[][] grid) {
int row = grid.length;
int col = grid[0].length;
int fresh = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == 1) {
fresh++;
}
}
}
if(fresh > 0)
return false;
return true;
}
//模拟一步腐化过程,也就是一分钟
public int[][] rotting(int[][] grid) {
int row = grid.length;
int col = grid[0].length;
int[][] temp = new int[row][col];
// copy
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
temp[i][j] = grid[i][j];
}
}
// rotting
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == 2) {
if (i - 1 >= 0 && grid[i - 1][j] == 1) {
temp[i - 1][j] = 2;
}
if (i + 1 < row && grid[i + 1][j] == 1) {
temp[i + 1][j] = 2;
}
if (j - 1 >= 0 && grid[i][j - 1] == 1) {
temp[i][j - 1] = 2;
}
if (j + 1 < col && grid[i][j + 1] == 1) {
temp[i][j + 1] = 2;
}
}
}
}
return temp;
}
}
这是能够直接想到的方法,它解决了问题,初步到达了我们的目标。但是明显它不够效率,冗余代码也较多。所以我们要思考有没有更好的方法去解决这个问题。
算法课学的东西我都忘得差不多了,哈哈,我想不到更好的办法了。嗯,只能借鉴一下其他人的思想了。等我彻底搞懂了再补充上来。
看了看官方的解答,感觉还是这个思路,我把代码改了改,减少了代码冗余度,时间复杂度并没有降低,运行时间跟以前一样都是4ms。
代码如下:
class Solution {
public int orangesRotting(int[][] grid) {
//存四个方向坐标,省的整四个if导致重复代码多
int[] dr = new int[]{-1, 0, 1, 0};
int[] dc = new int[]{0, -1, 0, 1};
Queue<Integer> queue = new ArrayDeque<Integer>();
Map<Integer,Integer> depth = new HashMap<Integer, Integer>();
int row = grid.length;
int col = grid[0].length;
for (int i = 0; i < row; i++) {
for(int j = 0; j < col; j++) {
if (grid[i][j] == 2) {
int code = i * col + j;
queue.add(code);
depth.put(code, 0);
}
}
}
int rs = 0;
while(!queue.isEmpty()) {
int code = queue.remove();
int r = code / col;
int c = code % col;
for(int k = 0 ; k < 4; k++) {
int nr = r + dr[k];
int nc = c + dc[k];
if(nr >=0 && nr < row && nc >= 0 && nc < col && grid[nr][nc] == 1) {
grid[nr][nc] = 2;
int ncode = nr * col + nc;
queue.add(ncode);
depth.put(ncode, depth.get(code) + 1);
rs = depth.get(ncode);
}
}
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == 1) {
return -1;
}
}
}
return rs;
}
}