LeetCode第2577题-在网格图中访问一个格子的最少时间-python实现-图解思路与手撕代码
文章目录
- 一、题目描述
- 二、解题思路与代码实现
- 1.解题思路
- 2.代码实现
- 总结
一、题目描述
二、解题思路与代码实现
1.解题思路
这道题求最短距离,首先检查起始点0,0的右边0,1和下边1,0,如果这两个点的值都大于1,那这道题无解,直接返回-1。
如果起始点的右边和下边都小于等于1,那就可以通过反复横跳的形式到达任意一个点,例如当前点是1,下一个点是3,那可以先跳到上一个点变成2,再跳回来变成3,这样就可以跳到下一个点变成4。
这样从当前点到周围点的距离要么是当前距离+1,要么是反复横跳之后+1。
如果需要反复横跳,那么到达这个点的时间和这个点的横纵坐标之和的奇偶性相同,这点可以证明。
所以最后的结果需要根据( i + j )的奇偶性判断是否要+1
最后为了保证最短距离,需要把所有遍历过的点都存储起来,每次取出最短距离的点检查其上下左右,这一点在代码的最后进一步讨论。
2.代码实现
代码如下(示例):
class Solution:
def minimumTime(self, grid: List[List[int]]) -> int:
m,n=len(grid),len(grid[0])
if grid[0][1]>1 and grid[1][0]>1:return -1
dis=[[inf]*n for _ in range(m)]
dis[0][0]=0
# h存储(距离,x,y),因为不知道那一条路线是最短路径,所有处理过的所有点都要存储起来
# 从h中不断取出距离最短的点,检查其上下左右,直到到达右下角
h=[(0,0,0)]
while True:
d,i,j = heappop(h)
if i==m-1 and j==n-1:return d
for x,y in (i-1,j),(i+1,j),(i,j-1),(i,j+1):
# 遍历(i,j)上下左右四个点
if 0<=x<m and 0<=y<n:
# 到周围点的距离要么是当前距离+1,要么是反复横跳之后+1
# 如果需要反复横跳以使得已经经过的时间大于周围点所要求的的最小时间
# 那么到达这个点的时间和这个点的横纵坐标之和的奇偶性相同
nd=max(d+1,grid[x][y])
nd+=(nd-x-y)%2
# 如果求出的nd小于dis中存储的值,就更新
if nd<dis[x][y]:
dis[x][y]=nd
heappush(h,(nd,x,y))
对于h的作用,我们可以在每次while循环中打印h的长度和内容检查其作用。
print(len(h))
print(h)
1
[(0, 0, 0)]
2
[(1, 0, 1), (5, 1, 0)]
3
[(2, 1, 1), (5, 1, 0), (4, 0, 2)]
4
[(3, 1, 2), (3, 2, 1), (4, 0, 2), (5, 1, 0)]
5
[(3, 2, 1), (5, 1, 0), (4, 0, 2), (8, 2, 2), (6, 1, 3)]
5
[(4, 0, 2), (4, 2, 0), (6, 1, 3), (8, 2, 2), (5, 1, 0)]
5
[(4, 2, 0), (5, 0, 3), (6, 1, 3), (8, 2, 2), (5, 1, 0)]
4
[(5, 0, 3), (5, 1, 0), (6, 1, 3), (8, 2, 2)]
3
[(5, 1, 0), (8, 2, 2), (6, 1, 3)]
2
[(6, 1, 3), (8, 2, 2)]
2
[(7, 2, 3), (8, 2, 2)]
可以发现,通过存储所有遍历过的点,并不断取出距离最小的点,可以实现最短路径的目的。
总结
这道题对于图和最短距离的讨论是非常有价值的。