题目
542. 01矩阵
难度:中等
给定一个由0和1组成的矩阵,找出每个元素到最近的0的距离。
两个相邻元素间的距离为1。
示例:
思路解析:
找到每个1到最近的0的距离。
1,首先考虑整个矩阵只有一个0的情况,那么设这个0的位置为(ni,nj),那么关于每个位置为(i,j)的1,它到这个0的位置为|i-ni|+|j-nj|。
2,再考虑整个矩阵有多个0的情况,我们需要找出最近的那个0。但是我们反向思考,我们可以找出距离所有的0最近的1,那么这些1到最近0的距离则为1;再找出距离所有已找到的节点最近的其他非0节点,那么这些1到最近0的距离就为2。
依次类推,首先找出所有0的所在位置并标记(其他位置均为1),通过这些值为0的位置找到离它们最近的值为1的位置并进行标记;再找到距离这些已标记的位置找到距离它们最近的未标记的位置;即可遍历到所有的位置。
代码实现:
static int[][] direction = {{1,0},{-1,0},{0,1},{0,-1}};
public int[][] updateMatrix(int[][] matrix) {
int xLength = matrix[0].length;
int yLength = matrix.length;
int[][] distance = new int[yLength][xLength];
boolean[][] seen = new boolean[yLength][xLength];
Queue<int[]> queue = new LinkedList<>();
//将所有的0的位置加入队列
for(int i = 0;i < yLength;i++){
for(int j = 0;j < xLength;j++){
if(matrix[i][j] == 0){
queue.add(new int[]{i,j});
distance[i][j] = 0;
seen[i][j] = true;
}
}
}
//遍历
while(!queue.isEmpty()){
int[] get = queue.poll();
int i = get[0];
int j = get[1];
for(int k = 0;k < 4;k++){
int ni = direction[k][0] + i;
int nj = direction[k][1] + j;
if(ni >= 0 && ni < yLength && nj >= 0 && nj < xLength && !seen[ni][nj]){
distance[ni][nj] = distance[i][j] + 1;
seen[ni][nj] = true;
queue.add(new int[]{ni,nj});
}
}
}
return distance;
}
代码解释:
distance数组保存距离值。
seen数组表示节点(i,j)是否被标记。
通过队列实现广度优先搜索。
第一批进入队列的位置为matrix数组中值为0的位置。
int[][] distance = new int[yLength][xLength];
boolean[][] seen = new boolean[yLength][xLength];
Queue<int[]> queue = new LinkedList<>();
//将所有的0的位置加入队列
for(int i = 0;i < yLength;i++){
for(int j = 0;j < xLength;j++){
if(matrix[i][j] == 0){
queue.add(new int[]{i,j});
distance[i][j] = 0;
seen[i][j] = true;
}
}
}
队列初始化后,开始遍历。
对于已进队的位置,找到关于这个位置(i,j)“上下左右”各个位置(ni,nj),如果这些位置没有被标记过,那么就表示它对最近0的距离没有计算过,那么直接将这个位置(ni,nj)到它最近0的距离设置为“位置(i,j)到它最近0的距离”+1(因为未被标记的节点距离越近,就越早被遍历到,所以可直接加1),并标记(ni,nj)位置,并加入队列。
//遍历
while(!queue.isEmpty()){
int[] get = queue.poll();
int i = get[0];
int j = get[1];
for(int k = 0;k < 4;k++){
int ni = direction[k][0] + i;
int nj = direction[k][1] + j;
if(ni >= 0 && ni < yLength && nj >= 0 && nj < xLength && !seen[ni][nj]){
distance[ni][nj] = distance[i][j] + 1;
seen[ni][nj] = true;
queue.add(new int[]{ni,nj});
}
}
}