Leetcode 542.01 矩阵
1 题目描述(Leetcode题目链接)
给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。两个相邻元素间的距离为 1 。
输入
0 0 0
0 1 0
0 0 0
输出
0 0 0
0 1 0
0 0 0
注意:
- 给定矩阵的元素个数不超过 10000。
- 给定矩阵中至少有一个元素是 0。
- 矩阵中的元素只在四个方向上相邻: 上、下、左、右。
2 题解
多源广度优先搜索,以所有0的位置为初始位置。
class Solution:
def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
m, n = len(matrix), len(matrix[0])
di = [(0, 1), (0, -1), (1, 0), (-1, 0)]
queue = []
for i in range(m):
for j in range(n):
if matrix[i][j] == 0:
queue.append((i, j))
dis = 0
asked = set(queue)
while queue:
num = len(queue)
while num:
num -= 1
i, j = queue.pop(0)
matrix[i][j] = dis
for d in di:
x, y = i+d[0], j+d[1]
if 0 <= x < m and 0 <= y < n and (x, y) not in asked:
queue.append((x, y))
asked.add((x, y))
dis += 1
return matrix
动态规划,定义
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]为位置
(
i
,
j
)
(i, j)
(i,j)到0的最近距离,因此初始化
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]各个元素无穷大,并将与matrix中0的对应位置初始化为0。注意到一个位置的状态由左上和右下来决定,因此需要遍历两遍。从左上方来的状态转移方程为:
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
]
[
j
]
,
1
+
d
p
[
i
−
1
]
[
j
]
,
1
+
d
p
[
i
]
[
j
−
1
]
)
dp[i][j] = min(dp[i][j], 1+dp[i-1][j], 1+dp[i][j-1])
dp[i][j]=min(dp[i][j],1+dp[i−1][j],1+dp[i][j−1])
从右下方来的状态转移方程为:
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
]
[
j
]
,
1
+
d
p
[
i
+
1
]
[
j
]
,
1
+
d
p
[
i
]
[
j
+
1
]
)
dp[i][j] = min(dp[i][j], 1+dp[i+1][j], 1+dp[i][j+1])
dp[i][j]=min(dp[i][j],1+dp[i+1][j],1+dp[i][j+1])
class Solution:
def updateMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
m, n = len(matrix), len(matrix[0])
dp = [([float("inf")]*n) for _ in range(m)]
for i in range(m):
for j in range(n):
if matrix[i][j] == 0:
dp[i][j] = 0
for i in range(m):
for j in range(n):
if i >= 1:
dp[i][j] = min(dp[i-1][j] + 1, dp[i][j])
if j >= 1:
dp[i][j] = min(dp[i][j-1] + 1, dp[i][j])
for i in range(m-1, -1, -1):
for j in range(n-1, -1, -1):
if i < m-1:
dp[i][j] = min(dp[i+1][j] + 1, dp[i][j])
if j < n-1:
dp[i][j] = min(dp[i][j+1] + 1, dp[i][j])
return dp