题目
解法1:BFS
这道题目第一眼看到的感觉应该是用BFS,但是如果直接用BFS对每个1的位置找最近的0的话,复杂度是会到O(m2 * n2), 这样会超时。那么换种思路,如果从0的位置出发去更新1呢,这样会很大程度减少复杂度,具体如下:
- 构建一个与matrix相同形状的dist矩阵,每个位置的值代表与0的最短距离
- 首先遍历一次matrix,将所有0的位置压入队列,并且所有0的位置相应dist中的值设为0
- 开始对队列中的元素进行BFS,从0出发,假设当前的位置为[i][j],向四周扩散找1的位置为[x][y],如果dist[x][y]>dist[i][j]+1的话,那么更新dist[x][y]的值,同时把这个[x][y]押入到队列
这样乍一看复杂度感觉是一样的,其实则不然,因为只有满足条件的位置才会被压入到队列中,所以复杂度会大大减小。leetcode官方给出的复杂度是O(mn),我个人觉得不能保证是O(mn),但一定比O(m2 * n2)小很多
python代码如下:
class Solution:
def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
# BFS解法
m,n = len(matrix),len(matrix[0])
dist = [[float('inf')]*n for _ in range(m)]
q = collections.deque()
for i in range(m):
for j in range(n):
if matrix[i][j] == 0:
dist[i][j] = 0
q.append((i,j))
dirs = [[0,1],[0,-1],[-1,0],[1,0]]
while q:
curr = q.popleft()
for d in dirs:
x = curr[0]+d[0]
y = curr[1]+d[1]
if x>=0 and x<m and y>=0 and y<n and matrix[x][y]==1:
if dist[x][y]>dist[curr[0]][curr[1]]+1:
dist[x][y] = dist[curr[0]][curr[1]]+1
q.append((x,y))
return dist
解法2:BFS
上面第一种BFS是从0出发,然后不断向外更新最短距离。在二刷的时候,自己想了一种从1出发的BFS。就是从每个1出发,一圈圈向外扩张,找到0时计算步数。对于这种方法就是每个1的位置进行一次BFS。值得注意的是,这边的BFS必须加visited防止成环,而第一种BFS不需要,因为第一种BFS只有在距离更新的情况下才会将当前位置加入队列,否则不会。这样已经被更新过的节点不会被重复加入,代码如下:
class Solution:
def updateMatrix(self, matrix: List[List[int]