M542.01 矩阵
dp, bfs, https://leetcode-cn.com/problems/01-matrix/
给定一个由 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.lengthn == mat[i].length1 <= m, n <= 10^41 <= m * n <= 10^4mat[i][j] is either 0 or 1.mat中至少有一个0
思路:从所有 0 同时出发做多源 BFS,一次性计算出所有 1 到最近 0 的距离。
多源 BFS(Multi-source BFS),核心思想:
- 把所有 0 的位置作为 BFS 的起点(初始队列)。
- 所有 0 的距离为 0。
- 然后向外一层层扩展,每扩展一层,距离 +1。
- 这样每个格子只被访问一次,时间复杂度 O(nm)。
python
from collections import deque
from typing import List
class Solution:
def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
n = len(mat)
m = len(mat[0])
# 初始化结果矩阵,0 的位置为 0,1 的位置设为 -1(表示未访问)
result = [[-1] * m for _ in range(n)]
queue = deque()
# 将所有 0 入队,并初始化 result
for i in range(n):
for j in range(m):
if mat[i][j] == 0:
result[i][j] = 0
queue.append((i, j))
# 四个方向
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
# 多源 BFS
while queue:
x, y = queue.popleft()
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < n and 0 <= ny < m and result[nx][ny] == -1:
result[nx][ny] = result[x][y] + 1
queue.append((nx, ny))
return result124ms,击败64.56%
python
from typing import List
from collections import deque
class Solution:
def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
m, n = len(mat), len(mat[0])
dp = [[float('inf')] * n for _ in range(m)]
queue = deque()
# 初始化,把所有 0 加入队列,结构为 (dist, i, j)
for i in range(m):
for j in range(n):
if mat[i][j] == 0:
dp[i][j] = 0
queue.append((0, i, j)) # 明确带 dist,便于调试、阅读
directions = [(-1,0), (1,0), (0,-1), (0,1)]
while queue:
dist, x, y = queue.popleft()
# 如果当前距离比 dp 更大,说明已被更新(可选的剪枝)
if dist > dp[x][y]:
continue
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < m and 0 <= ny < n:
if dp[nx][ny] > dist + 1:
dp[nx][ny] = dist + 1
queue.append((dp[nx][ny], nx, ny))
return dp
# 测试
if __name__ == "__main__":
mat = [[0,0,0],[0,1,0],[1,1,1]]
for row in Solution().updateMatrix(mat):
print(row)是 OJ01088:滑雪 的升级版。因为矩阵每个点的高度有更新,不能只用sort一次,需要使用heapq。
当路径代价不同、更新存在“早晚优先级”时,用堆有优势。否则 BFS 更快。
207ms,击败19.49%
python
import heapq
from typing import List
class Solution:
def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
m, n = len(mat), len(mat[0])
dp = [[float('inf')] * n for _ in range(m)]
heap = []
# 初始化,所有的0加入到堆中
for i in range(m):
for j in range(n):
if mat[i][j] == 0:
dp[i][j] = 0
heapq.heappush(heap, (0, i, j)) # (distance, x, y)
# 定义四个方向的移动
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
# 使用堆进行更新
while heap:
dist, x, y = heapq.heappop(heap)
# 如果当前的距离大于 dp[x][y],说明这个位置已经被更新过,不需要再次处理
if dist > dp[x][y]:
continue
# 对当前点的四个方向进行处理
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < m and 0 <= ny < n:
# 如果新位置的dp值可以更新(即发现更短的路径)
if dp[nx][ny] > dp[x][y] + 1:
dp[nx][ny] = dp[x][y] + 1
heapq.heappush(heap, (dp[nx][ny], nx, ny))
return dp
# 测试用例
if __name__ == "__main__":
mat = [[0,0,0],[0,1,0],[1,1,1]]
print(Solution().updateMatrix(mat))107ms,击败85.95%
python
from typing import List
from collections import deque
class Solution:
def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
m, n = len(mat), len(mat[0])
dp = [[float('inf')] * n for _ in range(m)]
queue = deque()
# 将所有0的元素加入队列并初始化dp数组
for i in range(m):
for j in range(n):
if mat[i][j] == 0:
dp[i][j] = 0
queue.append((i, j))
# 定义四个方向的移动
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
# BFS开始
while queue:
x, y = queue.popleft()
# 对当前点的四个方向进行处理
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < m and 0 <= ny < n:
# 如果新位置的dp值可以更新(即发现更短的路径)
if dp[nx][ny] > dp[x][y] + 1:
dp[nx][ny] = dp[x][y] + 1
queue.append((nx, ny))
return dp
# 测试用例
if __name__ == "__main__":
mat = [[0,0,0],[0,1,0],[1,1,1]]
print(Solution().updateMatrix(mat))python
from typing import List
class Solution:
def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
m, n = len(mat), len(mat[0])
dp = [[float('inf') for _ in range(n)] for _ in range(m)]
for i in range(m):
for j in range(n):
if mat[i][j] == 0:
dp[i][j] = 0
else:
if i > 0:
dp[i][j] = min(dp[i][j], dp[i-1][j]+1)
if j > 0:
dp[i][j] = min(dp[i][j], dp[i][j-1]+1)
for i in range(m-1, -1, -1):
for j in range(n-1, -1, -1):
if mat[i][j] == 0:
dp[i][j] = 0
else:
if i < m-1:
dp[i][j] = min(dp[i][j], dp[i+1][j]+1)
if j < n-1:
dp[i][j] = min(dp[i][j], dp[i][j+1]+1)
return dp
if __name__ == "__main__":
mat = [[0,0,0],[0,1,0],[0,0,0]]
print(Solution().updateMatrix(mat))