Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each cell.
The distance between two adjacent cells is 1.
Example 1:
Input:
0 0 0 0 0 0
0 1 0 -> 0 1 0
0 0 0 0 0 0
Example 2:
Input:
0 0 0 0 0 0
0 1 0 -> 0 1 0
1 1 1 1 2 1
Note:
1. The number of elements of the given matrix will not exceed 10,000.
2. There are at least one 0 in the given matrix.
3. The cells are adjacent in only four directions: up, down, left and right.
BFS。
先让所有的注水点O进q,接下来开始往1拓展,如果占到了就不能再让别人占了,因为先占到就说明是最近的,数字已经准了。
细节:
1.一定要所有O先一起入队,然后同时开始拓展搜索。本题不可以给每个O写个公用子函数bfs(),然后每个O都调用一次,如果看到别人占过的就更新一下。如果一共有n个点,这个方法不能保证每个点只被访问一次,而是会变成*O点个数次,从而整体时间复杂度为O(n^2),爆了O(n)了。
2.一圈一圈往外搜,要记录每圈的距离的时候,bfs要写的层级bfs,而不可以是stream bfs,否则dist就算错了。
3.bfs上下左右移动后一定要记得检查下标是否合格。
4.本题有一个省掉visited数组的小方法:需要visited的难点主要是难以区分1是来自于数组自带值还是已经访问过了距离确实是1.那么一开始遍历找0的时候顺便把所有1初始化为MAX_VALUE,那之后如果看到<MAX_VALUE的数字比如1的确就是因为已经访问过了赋值过值了,消除了歧义。
实现:
class Solution { public int[][] updateMatrix(int[][] matrix) { // P3: 这题不能让每个0都独立做一次bfs,然后遇到重复就更新,会TLE MLE。应该同时让所有O一起开始探索,谁先占到是谁的。 if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { return matrix; } int[] dx = {0, 1, 0, -1}; int[] dy = {1, 0, -1, 0}; boolean[][] isVisited = new boolean[matrix.length][matrix[0].length]; Queue<Integer> qx = new LinkedList<>(); Queue<Integer> qy = new LinkedList<>(); for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { if (matrix[i][j] == 0) { qx.offer(i); qy.offer(j); isVisited[i][j] = true; } } } int dist = 0; while (!qx.isEmpty()) { dist++; int size = qx.size(); for (int cnt = 0; cnt < size; cnt++) { int cx = qx.poll(); int cy = qy.poll(); for (int i = 0; i < 4; i++) { int nx = cx + dx[i]; int ny = cy + dy[i]; // P1: 上下左右移动后一定要注意检查下标越界!!! if (nx < 0 || nx >= matrix.length || ny < 0 || ny >= matrix[0].length || isVisited[nx][ny]) { continue; } matrix[nx][ny] = dist; isVisited[nx][ny] = true; qx.offer(nx); qy.offer(ny); } } } return matrix; } }