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 1 0 0 0 0
Output:
0 0 0 0 1 0 0 0 0
Example 2:
Input:
0 0 0 0 1 0 1 1 1
Output:
0 0 0 0 1 0 1 2 1
Note:
- The number of elements of the given matrix will not exceed 10,000.
- There are at least one 0 in the given matrix.
- The cells are adjacent in only four directions: up, down, left and right.
题目含义:给定一个只含0和1的矩阵,找到每个1到0的最短距离。 两个相邻单元格的距离是1
思路:每一轮以影响值来影响四周的目标值,如果目标值大于影响值+1,则目标值等于影响值+1。用形象的比喻来描述这道题的话,就是一颗石头扔入湖中时,它的影响波及周围,且向四周不断传播它的影响。
第一次更新
对待求矩阵进行一次变换,遇1元素设为最大值,遇0元素要记录row,col
值,并放入一个队列中。接下来是求解的核心了,我们只需要寻找到一种机制能够准确更新该数组就可以了。所以该算法的思想,就是首先把这些石头找出来【0元素】,更新规则是,一旦碰到【inf】,我就设一个该【0元素】对【inf】的影响值,此处为1。但由于【0元素】的影响是传递的,所以受它影响的【inf】节点必须得放入队列中,计算下次影响值。
第二次更新:以0作为冲击值(因为queue中的元素值都是0)
第二次更新中,[1,1]位置由inf改为1,是被[0,1]位置的0冲刷导致。改为1后,[1,0]和[1,2]位置的0将无法冲刷[1,1]。以[1,0]不能冲刷[1,1]为例,位置[1,1]的值1不满足大于[1,0]的值+1,也就是 [1,1]<=[1,0]+1
0元素周围的元素均被波及,接下来就是1元素的传递。
第三次更新: 以1作为冲击值(因为queue中的元素值都是1)
第四次更新: 以2作为冲击值(因为queue中的元素值都是2)
1 public int[][] updateMatrix(int[][] matrix) { 2 // 一定要看此地址,否则很那理解 http://blog.csdn.net/u014688145/article/details/64126559 3 int m = matrix.length; 4 int n = matrix[0].length; 5 Queue<int[]> q = new LinkedList<>(); 6 for (int i = 0; i < m; i++) { 7 for (int j = 0; j < n; j++) { 8 if (matrix[i][j] == 0) q.add(new int[]{i, j}); //把0元素加入队列中,以备波及影响周围元素 9 else matrix[i][j] = Integer.MAX_VALUE;//设为最大值,方便求0元素影响值 10 } 11 } 12 //溅起的涟漪,代表传播的四个方向 13 int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; 14 while (!q.isEmpty()) { 15 int[] cell = q.poll(); 16 for (int[] dirc : dirs) { 17 //需要比较的下一位置元素 18 int r = cell[0] + dirc[0]; 19 int c = cell[1] + dirc[1]; 20 21 //如果下一位置的元素值,小于等于(当前位置元素值+1),直接跳过 22 if (r < 0 || r >= m || c < 0 || c >= n || matrix[r][c] <= (matrix[cell[0]][cell[1]] + 1)) continue; 23 else { 24 matrix[r][c] = matrix[cell[0]][cell[1]] + 1; 25 q.offer(new int[]{r, c}); 26 } 27 } 28 } 29 return matrix; 30 }