📅  最后修改于: 2023-12-03 15:12:45.589000             🧑  作者: Mango
题目描述:
有一个二维的 n×m 的地图,地图上的每一个位置上可能有一个门或者是一个空位置,把所有门的位置作为起点,相同的门之间可以互相到达。定义一个点的唯一编码为它的行号与列号,用一个整数对 (x,y) 来表示,其中 x 表示行号,y 表示列号。你需要找出所有门每对之间的最短距离。如果门 i 与门 j 之间无法到达,则输出 "Impossible"。
编写一个函数 get_distance_map,接收一个 n*m 大小的整数二维数组 matrix,其中 matrix[i][j] 可以取值 0 或者是 1,其中 1 表示门,0 表示空位置。函数需要返回一个大小为 C(n,2) 的二维整数数组,其中第 i 行表示门之间的距离,依次为门 1 到 门 i+1, 门 i+2, ...... ,门 n 。如果两个门之间无法到达,则用 -1 表示。
示例:
输入:
matrix = [ [1, 0, 0, 1], [1, 1, 1, 0], [0, 0, 1, 1] ]
输出:
[ [-1, 3, 2], [3, -1, 1], [2, 1, -1] ]
解释:
如果两个门不相连,则用 -1 表示距离。
解题思路:
本题是一个典型的最短路径问题。题目要求我们找出所有门之间的最短距离,对于这种需要求出最短距离的场景,我们可以考虑使用广度优先搜索算法(BFS)来解决。
具体步骤如下:
时间复杂度为 O(nm(n+m)),空间复杂度为 O(nm)。
参考代码如下所示:
from typing import List
from queue import Queue
def bfs(matrix: List[List[int]], start: tuple) -> List[int]:
"""使用 BFS 计算最短距离"""
n, m = len(matrix), len(matrix[0])
dx, dy = [-1, 0, 1, 0], [0, 1, 0, -1] # 上右下左
visited = [[False] * m for _ in range(n)] # 记录是否访问过
dist = [-1] * n * m # 到每个点的距离
q = Queue()
x, y = start
q.put((x, y))
visited[x][y] = True
dist[x * m + y] = 0
while not q.empty():
x, y = q.get()
for i in range(4):
nx, ny = x + dx[i], y + dy[i]
if 0 <= nx < n and 0 <= ny < m and not visited[nx][ny]:
if matrix[nx][ny] == 1:
# 找到了另一个门
visited[nx][ny] = True
dist[start[0] * m + start[1] * n] = dist[nx * m + ny] = dist[x * m + y] + 1
elif matrix[nx][ny] == 0:
visited[nx][ny] = True
dist[nx * m + ny] = dist[x * m + y] + 1
q.put((nx, ny))
return dist
def get_distance_map(matrix: List[List[int]]) -> List[List[int]]:
n, m = len(matrix), len(matrix[0])
# 统计门的数量
count = 0
for i in range(n):
for j in range(m):
if matrix[i][j] == 1:
count += 1
if count == 0:
# 没有门
return [[]]
# 找出所有门的位置,并标记出其编号
doors = []
for i in range(n):
for j in range(m):
if matrix[i][j] == 1:
count -= 1
doors.append((i, j, len(doors)))
if count == 0:
break
else:
continue
break
# 计算门之间的最短距离
res = [[-1] * len(doors) for _ in range(len(doors))]
for i in range(len(doors)):
dist = bfs(matrix, doors[i][:2])
for j in range(i + 1, len(doors)):
res[i][j] = res[j][i] = dist[doors[j][0] * m + doors[j][1]]
return res
注:上述代码中的 get_distance_map 函数即为本题所需的函数,函数接收一个 n*m 大小的整数二维数组 matrix,其中 matrix[i][j] 可以取值 0 或者是 1,其中 1 表示门,0 表示空位置。函数返回一个大小为 C(n,2) 的二维整数数组,其中第 i 行表示门之间的距离,依次为门 1 到 门 i+1, 门 i+2, ...... ,门 n 。如果两个门之间无法到达,则用 -1 表示。