• LeetCode994.腐烂的橘子


     看完题我觉得这不是和上一道岛屿的题一样简单嘛,然后写了将近2个小时才写出来,我的思路就是,用check()先对grid检查一下,是否有以下情况:

    (如果有1的周围都是空,则这个位置用不腐烂,返回-1; 如果全是1,返回永不腐烂,返回-1;如果没有2,永不腐烂,则返回-1),

    定义一个hasFresh()方法看grid中是不是还有fresh的橘子1,然后在orangesRotting()方法算minute。

    就是在while(hasFresh())中对grid全部扫描一遍,如果有2,就把它放进栈中,扫描完了就把这些2的坐标拿出来,然后把2的周围的1变成2调用turnRot(),这算是变腐烂了1次,minute++,然后又是while去检查是否还有fresh,如果还有就继续腐烂,最后直到没有了fresh就跳出循环返回minute。

    但是如果是一列2,2,1,0,1,1就出现死循环了,因为第一个1腐烂后无法去腐烂后面但是又始终hasFresh,

    于是我加了一个visit布尔数组,如果发现了一个2并且它没有visit才把它放进栈,然后visit改为true表示已经用它腐烂过周围了不能再次腐烂周围了,下次扫面到这个2就不会放进栈了,那么上面的情况就当第一个1变成2并且visit后就没有可以放进栈的2了,所以扫描一遍后stack还是empty,所以当扫描一遍后stack还是empty的话直接返回-1,

    以下是我的代码:

    1. class Solution {
    2. public int orangesRotting(int[][] grid) {
    3. int m = grid.length;
    4. int n = grid[0].length;
    5. int minute =0;
    6. boolean[][] visit = new boolean[m][n];
    7. if(check(grid) == -1)return -1;
    8. while(hasFresh(grid)){
    9. Stack stack = new Stack<>();
    10. for(int i =0;i
    11. for(int j=0;j
    12. if(grid[i][j] == 2 && visit[i][j] == false){
    13. visit[i][j] = true;
    14. Integer[] index = new Integer[]{i,j};
    15. stack.push(index);
    16. }
    17. }
    18. }
    19. if(stack.isEmpty()){
    20. return -1;
    21. }
    22. while(!stack.isEmpty()){
    23. Integer[] a = stack.pop();
    24. grid = turnRot(grid, a[0], a[1]);
    25. }
    26. minute++;
    27. }
    28. return minute;
    29. }
    30. public int[][] turnRot(int[][] grid, int i, int j){
    31. if(i-1>=0 && grid[i-1][j]==1)grid[i-1][j] = 2;
    32. if(i+11][j]==1)grid[i+1][j] = 2;
    33. if(j-1>=0 && grid[i][j-1]==1)grid[i][j-1] = 2;
    34. if(j+10].length && grid[i][j+1]==1)grid[i][j+1] = 2;
    35. return grid;
    36. }
    37. public boolean hasFresh(int[][] grid){
    38. int m = grid.length;
    39. int n = grid[0].length;
    40. for(int i =0;i
    41. for(int j=0;j
    42. if(grid[i][j] == 1)return true;
    43. }
    44. }
    45. return false;
    46. }
    47. public int check(int[][] grid){
    48. int m = grid.length;
    49. int n = grid[0].length;
    50. //如果有1的周围都是空,则这个位置用不腐烂,返回-1
    51. for(int i =0;i
    52. for(int j=0;j
    53. if((grid[i][j] == 1)){
    54. if(i-1>=0 && grid[i-1][j]!=0)continue;
    55. if(i+11][j]!=0)continue;
    56. if(j-1>=0 && grid[i][j-1]!=0)continue;
    57. if(j+10].length && grid[i][j+1]!=0)continue;
    58. return -1;
    59. }
    60. }
    61. }
    62. if(statuCode == 0)return 0;
    63. //如果全是1,返回永不腐烂,返回-1
    64. statuCode = -1;
    65. for(int i =0;i
    66. for(int j=0;j
    67. if(grid[i][j] != 1){
    68. statuCode =1;
    69. }
    70. }
    71. }
    72. if(statuCode == -1)return -1;
    73. //如果没有2,用不腐烂,则返回-1
    74. statuCode =-1;
    75. for(int i =0;i
    76. for(int j=0;j
    77. if(grid[i][j] == 2){
    78. statuCode=1;
    79. }
    80. }
    81. }
    82. if(statuCode == -1)return -1;
    83. return 1;
    84. }
    85. }

    我这个算法写的太屎了,尤其是check方法全靠一种一种情况排除,还是看看官方题解吧,写到这里的时候,我想去看看check方法能不能优化一下,把有些情况放一起check,比如那个全是1就不用判断了,因为它包含在没有2的情况里面,但是你猜怎么了?

    我发现有了visit数组后,check中的所有情况都不用check,因为他们都是使得stack为空,直接返回-1了,我只能说牛逼。所以可以删掉check方法,改成代码如下:

    1. class Solution {
    2. public int orangesRotting(int[][] grid) {
    3. int m = grid.length;
    4. int n = grid[0].length;
    5. int minute =0;
    6. boolean[][] visit = new boolean[m][n];
    7. while(hasFresh(grid)){
    8. Stack stack = new Stack<>();
    9. for(int i =0;i
    10. for(int j=0;j
    11. if(grid[i][j] == 2 && visit[i][j] == false){
    12. visit[i][j] = true;
    13. Integer[] index = new Integer[]{i,j};
    14. stack.push(index);
    15. }
    16. }
    17. }
    18. if(stack.isEmpty()){
    19. return -1;
    20. }
    21. while(!stack.isEmpty()){
    22. Integer[] a = stack.pop();
    23. grid = turnRot(grid, a[0], a[1]);
    24. }
    25. minute++;
    26. }
    27. return minute;
    28. }
    29. public int[][] turnRot(int[][] grid, int i, int j){
    30. if(i-1>=0 && grid[i-1][j]==1)grid[i-1][j] = 2;
    31. if(i+11][j]==1)grid[i+1][j] = 2;
    32. if(j-1>=0 && grid[i][j-1]==1)grid[i][j-1] = 2;
    33. if(j+10].length && grid[i][j+1]==1)grid[i][j+1] = 2;
    34. return grid;
    35. }
    36. public boolean hasFresh(int[][] grid){
    37. int m = grid.length;
    38. int n = grid[0].length;
    39. for(int i =0;i
    40. for(int j=0;j
    41. if(grid[i][j] == 1)return true;
    42. }
    43. }
    44. return false;
    45. }
    46. }

    看看官方题解的做法吧,题解用的叫多源广度优先搜索,和上一道题岛屿的数量的解法差不多,先上代码:

    1. class Solution {
    2. int[] dr = new int[]{-1, 0, 1, 0};
    3. int[] dc = new int[]{0, -1, 0, 1};
    4. public int orangesRotting(int[][] grid) {
    5. int R = grid.length, C = grid[0].length;
    6. Queue queue = new ArrayDeque();
    7. Map depth = new HashMap();
    8. for (int r = 0; r < R; ++r) {
    9. for (int c = 0; c < C; ++c) {
    10. if (grid[r][c] == 2) {
    11. int code = r * C + c;
    12. queue.add(code);
    13. depth.put(code, 0);
    14. }
    15. }
    16. }
    17. int ans = 0;
    18. while (!queue.isEmpty()) {
    19. int code = queue.remove();
    20. int r = code / C, c = code % C;
    21. for (int k = 0; k < 4; ++k) {
    22. int nr = r + dr[k];
    23. int nc = c + dc[k];
    24. if (0 <= nr && nr < R && 0 <= nc && nc < C && grid[nr][nc] == 1) {
    25. grid[nr][nc] = 2;
    26. int ncode = nr * C + nc;
    27. queue.add(ncode);
    28. depth.put(ncode, depth.get(code) + 1);
    29. ans = depth.get(ncode);
    30. }
    31. }
    32. }
    33. for (int[] row: grid) {
    34. for (int v: row) {
    35. if (v == 1) {
    36. return -1;
    37. }
    38. }
    39. }
    40. return ans;
    41. }
    42. }

    它每个元素用序号(行号*每行的个数+列好)来表示,用一个队列来装一层的2的序号,然后用一个Map depth表示每个节点的深度,key是序号,value是腐烂时间,他的腐烂时间其实就是父节点的腐烂时间+1,然后遍历完一次就把队列里的2取出来反向解出行号和列号,然后把周围腐烂,把周围的序号放进队列,把所有时间,也就是父节点时间+1放入map,然后取出时间,因为每次所放入的时间都是上一次的时间+1,所以最后一次的时间就是最大时间,所以最后返回ans是没有问题的,在返回之前先检查一遍,如果还有没腐烂的橘子1就返回-1。

  • 相关阅读:
    【OpenDDS开发指南V3.20】第三章:服务质量
    如何给Nginx配置访问IP白名单
    一级建造师从业者面试需要注意什么问题?
    复习单片机:IO串转并(内含:1. 74HC595 芯片介绍+2. 硬件设计+3. 软件设计+4.原始代码+5. 实验现象)
    【云开发】小程序端操作数据库详解
    (七)文件——PHP
    【小白专用】安装Apache2.4+ 安装PHP8.2+ php与sql server 2008 r2连接测试教程
    斩获双奖|易知微荣获“2021中国数字孪生解决方案优秀供应商”“中国智能制造优秀推荐产品”双奖项!
    Vue3+node.js网易云音乐实战项目(七)
    小程序里面循环使用ref的话获取不到
  • 原文地址:https://blog.csdn.net/qq_61009660/article/details/134484187