8## 【LeetCode】 01矩阵 (BFS/DFS)
给定一个由 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
一、广度优先搜索(树的BFS与图的BFS)
思路:
对于 「Tree 的 BFS」 (典型的「单源 BFS」) 大家都已经轻车熟路了:
首先把 root 节点入队,再一层一层无脑遍历就行了。
对于 「图 的 BFS」 (「多源 BFS」) 做法其实也是一样滴~,与 「Tree 的 BFS」的区别注意以下两条就 ok 辣~
Tree 只有 1 个 root,而图可以有多个源点,所以首先需要把多个源点都入队;
Tree 是有向的因此不需要标识是否访问过,而对于无向图来说,必须得标志是否访问过哦!并且为了防止某个节点多次入队,需要在其入队之前就将其设置成已访问!【 看见很多人说自己的 BFS 超时了,坑就在这里哈哈哈
做法:
根据上述思路,本题怎么做就很简单了:
首先把每个源点 0 入队,然后从各个 0 同时开始一圈一圈的向 1 扩散(每个 1 都是被离它最近的 0 扩散到的 ),扩散的时候可以设置 int[][] dist 来记录距离(即扩散的层次)并同时标志是否访问过。对于本题是可以直接修改原数组 int[][] matrix 来记录距离和标志是否访问的,这里要注意先把 matrix 数组中 1 的位置设置成 -1 (设成Integer.MAX_VALUE啦,m * n啦,10000啦都行,只要是个无效的距离值来标志这个位置的 1 没有被访问过就行辣~)
public int[][] updateMatrix(int[][] matrix) {
// 首先将所有的 0 都入队,并且将 1 的位置设置成 -1,表示该位置是 未被访问过的 1
Queue<int[]> queue = new LinkedList<>();
int m = matrix.length, n = matrix[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == 0) {
queue.offer(new int[] {i, j});
} else {
matrix[i][j] = -1;
}
}
}
int[] dx = new int[] {-1, 1, 0, 0};
int[] dy = new int[] {0, 0, -1, 1};
while (!queue.isEmpty()) {
int[] point = queue.poll();
int x = point[0], y = point[1];
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
// 如果四邻域的点是 -1,表示这个点是未被访问过的 1
// 所以这个点到 0 的距离就可以更新成 matrix[x][y] + 1。
if (newX >= 0 && newX < m && newY >= 0 && newY < n
&& matrix[newX][newY] == -1) {
matrix[newX][newY] = matrix[x][y] + 1;
queue.offer(new int[] {newX, newY});
}
}
}
return matrix;
}
二、深度优先搜索(DFS)
private int row;
private int col;
private int[][] vector = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int[][] updateMatrix(int[][] matrix) {
row = matrix.length;
col = matrix[0].length;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
// 优化:如果元素在 0 附近,保留元素值 1,不在 0 附近,初始化为一个较大值
if (matrix[i][j] == 1
&& !((i > 0 && matrix[i - 1][j] == 0)
|| (i < row - 1 && matrix[i + 1][j] == 0)
|| (j > 0 && matrix[i][j - 1] == 0)
|| (j < col - 1 && matrix[i][j + 1] == 0))) {
matrix[i][j] = row + col;
}
}
}
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
// 优化:将元素值为 1 的点作为深搜起点,降低递归深度
if (matrix[i][j] == 1) {
DFS(matrix, i, j);
}
}
}
return matrix;
}
private void DFS(int[][] matrix, int r, int c) {
// 搜索上下左右四个方向
for (int[] v : vector) {
int nr = r + v[0], nc = c + v[1];
if (nr >= 0 && nr < row
&& nc >= 0 && nc < col
&& matrix[nr][nc] > matrix[r][c] + 1) {
matrix[nr][nc] = matrix[r][c] + 1;
DFS(matrix, nr, nc);
}
}
}
作者:sweetiee
链接:https://leetcode-cn.com/problems/01-matrix/solution/2chong-bfs-xiang-jie-dp-bi-xu-miao-dong-by-sweetie/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。