LeetCode542-01矩阵

题目链接

英文链接:https://leetcode.com/problems/01-matrix/

中文链接:https://leetcode-cn.com/problems/01-matrix/

题目详述

给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。

两个相邻元素间的距离为 1 。

示例 1:
输入:

1
2
3
0 0 0
0 1 0
0 0 0

输出:

1
2
3
0 0 0
0 1 0
0 0 0

示例 2:
输入:

1
2
3
0 0 0
0 1 0
1 1 1

输出:

1
2
3
0 0 0
0 1 0
1 2 1

注意:

  1. 给定矩阵的元素个数不超过 10000。
  2. 给定矩阵中至少有一个元素是 0。
  3. 矩阵中的元素只在四个方向上相邻: 上、下、左、右。

题目详解

BFS。

  • BFS 相较于 DFS,一个很重要的特性的就是可以求“最小值”,如最短距离、最小步数等。
  • BFS 的队列可以分层来看,一层层向外扩展:第一次先把所有距离为 0 的点加入队列,第二次把所有距离为 1 的点加入队列,依此类推,这样求出的值就是最小值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class LeetCode_00542 {

public int[][] updateMatrix(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
int[][] res = new int[m][n];
for (int[] arr : res) {
Arrays.fill(arr, -1); // 初始化为 -1 表示未访问过
}
class Position {
int x, y;

public Position(int x, int y) {
this.x = x;
this.y = y;
}
}
Queue<Position> queue = new ArrayDeque<>();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (matrix[i][j] == 0) {
res[i][j] = 0;
queue.offer(new Position(i, j));
}
}
}
int[] dirs = new int[]{-1, 0, 1, 0, -1};
while (!queue.isEmpty()) {
Position pos = queue.poll();
for (int i = 0; i < 4; ++i) {
int x = pos.x + dirs[i], y = pos.y + dirs[i + 1];
if (x >= 0 && x < m && y >= 0 && y < n && res[x][y] == -1) { // 未访问才继续
res[x][y] = res[pos.x][pos.y] + 1;
queue.offer(new Position(x, y));
}
}
}
return res;
}
}

也可以运用动态规划,由于每个点距离 0 最近的距离来源于上下左右四个方向,为了避免循环依赖,我们可以从从左上方往右下方扫一遍,再从右下方往左上方扫一遍,这样可以求得每个点的最小距离。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class LeetCode_00542 {

public int[][] updateMatrix(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
int[][] res = new int[m][n];
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (matrix[i][j] == 1) {
res[i][j] = 0x3f3f3f3f;
if (i > 0) {
res[i][j] = Math.min(res[i][j], res[i - 1][j] + 1);
}
if (j > 0) {
res[i][j] = Math.min(res[i][j], res[i][j - 1] + 1);
}
}
}
}
for (int i = m - 1; i >= 0; --i) {
for (int j = n - 1; j >= 0; --j) {
if (i < m - 1) {
res[i][j] = Math.min(res[i][j], res[i + 1][j] + 1);
}
if (j < n - 1) {
res[i][j] = Math.min(res[i][j], res[i][j + 1] + 1);
}
}
}
return res;
}
}