欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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;
    }
}