994.腐烂的橘子


994.腐烂的橘子

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

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

每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。

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

示例 1:

img

输入: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 。

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 10
  • grid[i][j] 仅为 012

题解:

class Solution {
    public int orangesRotting(int[][] grid) {
        int[] direcrow = {-1, 0, 1, 0};
        int[] direccol = {0, -1, 0, 1};
        // 保存所有烂橘子的坐标到queue中
        Queue<Integer> queue = new ArrayDeque<>();
        // 保存橘子腐烂的时间
        Map<Integer, Integer> map = new HashMap();
        int R = grid.length;
        int C = grid[0].length;
        for (int i = 0; i < R; i++) {
            for (int j = 0; j < C; j++) {
                if (grid[i][j] == 2) {
                    // 按照行优先保存坐标
                    int dir = i * C + j;
                    queue.add(dir);
                    // 初始化一开始就有的烂橘子时间
                    map.put(dir, 0);
                }
            }
        }

        int minute = 0;
        // 一直循环知道取出所有的烂橘子
        while (!queue.isEmpty()) {
            int dir = queue.remove();
            // 将取出的坐标转换成对应的行和列
            int i = dir / C;
            int j = dir % C;
            // 开始往四个方向感染
            for (int k = 0; k < 4; k++) {
                int newr = i + direcrow[k];
                int newc = j + direccol[k];
                if (newr >= 0 && newr < R && newc >= 0 && newc < C && grid[newr][newc] == 1) {
                    grid[newr][newc] = 2;
                    int newDir = newr * C + newc;
                    queue.add(newDir);
                    map.put(newDir, map.get(dir) + 1);
                    minute = map.get(newDir);
                }
            }
        }

        for (int[] r : grid) {
            for (int c : r) {
                if (c == 1) {
                    return -1;
                }
            }
        }
        return minute;
    }
}


/**
    0:空单元格
    1:新鲜橘子
    2:腐烂橘子
*/
// class Solution {
//     // 横方向
//     int[] dr = new int[]{-1, 0, 1, 0};
//     // 纵方向
//     int[] dc = new int[]{0, -1, 0, 1};

//     public int orangesRotting(int[][] grid) {
//         int R = grid.length, C = grid[0].length;
//         Queue<Integer> queue = new ArrayDeque<Integer>();
//         Map<Integer, Integer> depth = new HashMap<Integer, Integer>();
//         for (int r = 0; r < R; ++r) {
//             for (int c = 0; c < C; ++c) {
//                 if (grid[r][c] == 2) {
//                     /**
//                         将烂橘子所在的位置按照列行先存储保存起来
//                         行优先存储:
//                         例如二维数组A[3][4],烂橘子所在位置A[2][3],按照行优先
//                         所以就是i * n + j即2 * 4 + 3
//                         如下就是r * C + c
//                      */
//                     int code = r * C + c;
//                     // 将每一行烂橘子位置按照行优先算出的位置记录进队列中
//                     queue.add(code);
//                     // map存储橘子变为腐烂时的时间,key为橘子的一维数组下标(行优先变的),value为变腐烂的时间
//                     depth.put(code, 0);
//                 }
//             }
//         }
//         int ans = 0;
//         // 当队列里还有烂橘子时
//         while (!queue.isEmpty()) {
//             // 取出队列中的烂橘子
//             int code = queue.remove();
//             // 将行优先算出的坐标位置还原成具体的哪一行哪一列
//             int r = code / C, c = code % C;
//             // 烂橘子开始往四个方向感染
//             for (int k = 0; k < 4; ++k) {
//                 int nr = r + dr[k];
//                 int nc = c + dc[k];
//                 // 为了防止烂橘子在矩阵的边上进行计算的时候导致溢出,需要对边界进行判断
//                 // 同时判断烂橘子的四个方向上是不是新鲜橘子
//                 if (0 <= nr && nr < R && 0 <= nc && nc < C && grid[nr][nc] == 1) {
//                     // 把新鲜橘子感染
//                     grid[nr][nc] = 2;
//                     // 同样的通过行优先保存被感染的橘子坐标,并放入队列中
//                     int ncode = nr * C + nc;
//                     queue.add(ncode);
//                     // 腐烂橘子上下左右新鲜橘子被腐烂的时间应该是一致的
//                     depth.put(ncode, depth.get(code) + 1);
//                     ans = depth.get(ncode);
//                 }
//             }
//         }
//         for (int[] row: grid) {
//             for (int v: row) {
//                 if (v == 1) {
//                     return -1;
//                 }
//             }
//         }
//         return ans;
//     }
// }

文章作者: Feliks
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Feliks !
评论
  目录