给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。 两个相邻元素间的距离为 1 。
在一个矩阵里只有0和1两种数字,求出每一个元素到最近一个0的距离,如果元素本身为0,则距离为0,在找最近0的过程只有四个方向,上下左右
从题目描述来看,不难得出我们在求某个元素的最近一个0的距离时,可以根据旁边的元素得到,因此我们可以使用动态规划
同时对于每一个元素1,我们可以从这个元素的上下左右去寻找一个最近的0,类似于广度优先遍历,因此我们也可以考虑用BFS的思想去完成
1. 动态规划
public int[][] updateMatrix(int[][] matrix) {
// 动态规划
int col = matrix[0].length;
int row = matrix.length;
int[][] dist = new int[row][col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (matrix[i][j] != 0) {
// 如果矩阵的值不为0,则设置一个较大的值
dist[i][j] = Integer.MAX_VALUE / 2;
}
}
}
// 左上
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (i > 0) {
// 上方元素
dist[i][j] = Math.min(dist[i][j], 1 + dist[i - 1][j]);
}
if (j > 0) {
// 左方元素
dist[i][j] = Math.min(dist[i][j], 1 + dist[i][j - 1]);
}
}
}
// 右下,注意遍历的顺序
for (int i = row - 1; i >= 0; i--) {
for (int j = col - 1; j >= 0; j--) {
if (i < row - 1) {
// 当不是最后一行时,得到自己与(下方元素值+1)的较小值
dist[i][j] = Math.min(dist[i][j], 1 + dist[i + 1][j]);
}
if (j < col - 1) {
// 右方元素
dist[i][j] = Math.min(dist[i][j], 1 + dist[i][j + 1]);
}
}
}
return dist;
}
2. BFS
// 代表上下左右四个方向
static int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
public int[][] updateMatrix(int[][] matrix) {
// BFS
int col = matrix[0].length;
int row = matrix.length;
// 每个队列的元素保存的是一个坐标
Queue<int[]> queue = new LinkedList<>();
// 保存矩阵中的每个元素是否被访问
int isVisited[][] = new int[row][col];
int dist[][] = new int[row][col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (matrix[i][j] == 0) {
queue.offer(new int[]{i, j});
isVisited[i][j] = 1;
}
}
}
while (!queue.isEmpty()) {
int[] ele = queue.poll();
int i = ele[0];
int j = ele[1];
// 对于元素的上下左右四个元素进行相应处理
for (int k = 0; k < 4; k++) {
int ii = i + dirs[k][0];
int jj = j + dirs[k][1];
if (ii > 0 && jj > 0 && ii < row && jj < col && isVisited[ii][jj] == 0) {
dist[ii][jj] = dist[i][j] + 1;
queue.offer(new int[]{ii, jj});
isVisited[ii][jj] = 1;
}
}
}
return dist;
}