传送门:https://leetcode-cn.com/problems/01-matrix/
给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。
两个相邻元素间的距离为 1 。
示例 1:
输入:0 0 0
0 1 0
0 0 0
输出:0 0 0
0 1 0
0 0 0
示例 2:
输入:0 0 0
0 1 0
1 1 1
输出:0 0 0
0 1 0
1 2 1
注意:给定矩阵的元素个数不超过 10000。
给定矩阵中至少有一个元素是 0。
矩阵中的元素只在四个方向上相邻: 上、下、左、右。
这个题我一开始也是想用泛洪法去检测,当遇到1的时候就开始向四周看到达0的最短距离,但是我发现这样做实现不了,而且扫描浪费时间也很大。遂去看解析。
看了这个解析的BFS解法,我有点明白了。下面讲讲我个人理解的思路。
新建一个queue用于保存已经扫描过节点的XY坐标,新建一个visited数组用于判别当前的位置是否已经访问过,result数组用于保存结果。
第一轮先对整个传入的数组进行遍历,扫描到0的直接入队、保存到visited数组并且将对应的result位置设置为0
因为当前位置为0的不需要去看其他节点是否为0,它本身就是可以满足条件的。
当第一轮做完以后,我们再取队列中的元素,分别让他上下左右移动。
if(newX>=0 && newY>=0 && newX < matrix.length && newY< matrix[0].length && !visit[newX][newY])
这行代码用于判断是否越界或者是已经访问过,如果是就直接跳到下一次移动操作。
visit[newX][newY] = true; res[newX][newY] = res[x][y] + 1; queue.add(new Integer[]{newX,newY});
因为matrix中所有为1的节点都是没有访问过的,所以先将visited数组置为true以表示这次访问到了。
然后将其值直接改为res[x][y](当前节点为0)+1(从0开始1步就可以访问到这个1节点)。
然后将最新的节点添加到队列中,以防止出现 [1,1,1]这种多个1包含在一起的情况。
总体代码:
1 class Solution { 2 public int[][] updateMatrix(int[][] matrix) { 3 if(matrix == null || matrix.length == 0){ 4 return null; 5 } 6 int[][] direction = new int[][] {{-1,0},{1,0},{0,-1},{0,1}}; 7 Queue<Integer[]>queue = new LinkedList<>(); 8 int m = matrix.length, n = matrix[0].length; 9 boolean[][] visit = new boolean[m][n]; 10 int[][] res = new int[m][n]; 11 for(int i = 0; i < m;i++){ 12 for(int j = 0; j < n;j++){ 13 if(matrix[i][j] == 0){ 14 queue.add(new Integer[]{i,j}); 15 visit[i][j] = true; 16 res[i][j] =0; 17 } 18 } 19 } 20 21 while(!queue.isEmpty()){ 22 Integer[] temp = queue.poll(); 23 int x = temp[0]; 24 int y = temp[1]; 25 for(int i = 0; i < direction.length;i++){ 26 int newX = x + direction[i][0]; 27 int newY = y+ direction[i][1]; 28 if(newX>=0 && newY>=0 && newX < matrix.length && newY< matrix[0].length && !visit[newX][newY]){ 29 visit[newX][newY] = true; 30 res[newX][newY] = res[x][y] + 1; 31 queue.add(new Integer[]{newX,newY}); 32 } 33 } 34 } 35 return res; 36 } 37 }