542. 01 矩阵
中 等 \color{#FFB800}{中等} 中等
给定一个由
0
和1
组成的矩阵mat
,请输出一个大小相同的矩阵,其中每一个格子是mat
中对应位置元素到最近的0
的距离。
两个相邻元素间的距离为1
。
示例 1:
输入:mat = [[0,0,0],[0,1,0],[0,0,0]]
输出:[[0,0,0],[0,1,0],[0,0,0]]
示例 2:
输入:mat = [[0,0,0],[0,1,0],[1,1,1]]
输出:[[0,0,0],[0,1,0],[1,2,1]]
提示:
m == mat.length
n == mat[i].length
- 1 <= m, n <= 104
- 1 <= m * n <= 104
mat[i][j] is either 0 or 1.
mat
中至少有一个0
方法1:多源广度优先搜索
我们先关注普通的广度优先搜索。先假设地图中有且仅有一个0
。
题目中提到,每一个格子是 mat
中对应位置元素到最近的 0
的距离,那么反过来,每一个格子的值是0
到这个元素的距离。这样一来,我们的出发点就清晰多了。我们可以从值为0
的土地出发进行广度优先搜索,每次向外扩展时,土地周围的4块土地值为1
;然后从值为1
的土地向周围4个格子扩展,周围土地的值为2
,以此类推。第i轮中遍历出来的所有土地的值也是i
(这里的i
从1开始计数)。
以一块4x4的mat
为例,其中(1,1)处为0
,过程如下:
_ _ _ _ _ 1 _ _ 2 1 2 _ 2 1 2 3 2 1 2 3
_ 0 _ _ ==> 1 0 1 _ ==> 1 0 1 2 ==> 1 0 1 2 ==> 1 0 1 2
_ _ _ _ _ 1 _ _ 2 1 2 _ 2 1 2 3 2 1 2 3
_ _ _ _ _ _ _ _ _ 2 _ _ 3 2 3 _ 3 2 3 4
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/01-matrix/solution/01ju-zhen-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
上述示例来自LeetCode官方题解
此外,我们还需要一个数组seen
来存储哪些土地被访问过了,以免再次被加入到队列中。例如下方的例子:
1 _ _
0 1 _
1 _ _
我们已经从左边的0
扩展到了中间的1
,接下来我们应该往“上右下”3个方向扩展,左侧应该被忽略。
我们其实在【LeetCode学习计划】《算法-入门-C++》第7天 广度优先搜索 / 深度优先搜索这篇文章中的733. 图像渲染和695. 岛屿的最大面积这两道题,已经遇到过用于记录土地是否访问过的数组了。这两道题中,由于我们遍历完的土地已经不需要了,所以土地的值被设为了0
,而这个“值设为0
”的操作就相当于我们对这块土地记为已访问过的操作。用于记录是否被访问过的数组被我们抽象到地图本身了。而这一题,我们最后的结果都是有用的,所以不能抛弃。
当然,你可以作一次判断,如果即将赋予的值小于土地当前的值,那么就覆盖原值并加入队列重新扩展,但那样就太扯了。假设你的矩阵里全是0
,而且按照这个思路,对于每一个0
都要将整个矩阵遍历一次。将整个矩阵赋值完成后,因为不能确定每个土地的值到自己近还是到别的0
近,下一个0
又要将整个(几乎)矩阵重新遍历一次,。看一下下面的例子:
0 0 0 0 0 1 2 3 0 0 1 2 0 0 0 0 0 0 0 0
0 0 0 0 => 1 2 3 4 => 1 1 2 3 => ... => 0 1 1 1 => 0 0 1 1
0 0 0 0 2 3 4 5 2