题目
给定一个由 0 和 1 组成的矩阵 mat ,请输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。
两个相邻元素间的距离为 1 。
示例
输入:mat = [[0,0,0],[0,1,0],[0,0,0]]
输出:[[0,0,0],[0,1,0],[0,0,0]]
输入:mat = [[0,0,0],[0,1,0],[1,1,1]]
输出:[[0,0,0],[0,1,0],[1,2,1]]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/01-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法1
多源点的BFS。
要更新数组中的每一个数,更新为到它的步数。
Java实现1
class Solution {
public int[][] updateMatrix(int[][] mat) {
int row = mat.length, col = mat[0].length;
int[] directions = {-1, 0, 1, 0, -1}; //移动方向
Queue<int[]> q = new LinkedList<>();
int step = 1;
//要找0到1的距离,所有0入队,非0置为负数
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++){
if (mat[i][j] == 0) q.offer(new int[]{i, j});
//标记非零元素为负,和遍历后设定的正数距离加以区分。
else mat[i][j] = -1;
}
}
while (!q.isEmpty()){
int sz = q.size();
//遍历当前队列中所有元素。
for (int i = 0; i < sz; i++){
int[] cur = q.poll();
//上、右、下、左,4个方向依次走一步
for (int j = 0; j < directions.length - 1; j++){
int x = cur[0] + directions[j];
int y = cur[1] + directions[j + 1];
//如果超出矩阵范围、是0元素、或已经设置过step,则跳过
if (x < 0 || x >= row || y < 0 || y >= col || mat[x][y] >= 0) continue;
//设置步数、存进队列里(下一层)。
mat[x][y] = step;
q.offer(new int[] {x, y});
}
}
step++;
}
return mat;
}
}
Java实现2
class Solution {
// 方向
static int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
public int[][] updateMatrix(int[][] mat) {
int m = mat.length,n = mat[0].length;
// 记录已访问的节点
boolean[][] visited = new boolean[m][n];
// 初始队列
Queue<int[]> queue = new LinkedList<>();
for (int i = 0; i < mat.length; i++) {
for (int j = 0; j < mat[0].length; j++) {
// 所有0全部入队
if (mat[i][j] == 0) {
queue.offer(new int[]{i, j});
visited[i][j] = true;
}
}
}
// 记录距离
int[][] dist = new int[m][n];
// 搜索0位置的四周,并记录距离
while (!queue.isEmpty()) {
int[] cur = queue.poll();
int row = cur[0], cln = cur[1];
for (int i = 0; i < 4; i++) {
int ni = row + dirs[i][0];
int nj = cln + dirs[i][1];
if (ni >= 0 && nj >= 0 && ni < m && nj < n && !visited[ni][nj]) {
dist[ni][nj] = dist[row][cln] + 1;
queue.offer(new int[]{ni, nj});
visited[ni][nj] = true;
}
}
}
return dist;
}
}