求解最短路径的问题,分为使用BFS和使用迪斯科特拉算法,这两种算法求解的范围是有区别的
BFS
适合求解,边的权值都是1的图中的最短路径的问题
图论 之 BFS
迪斯科特拉算法
适合求解边的权值不一样的图,其中,该算法有两种实现方式,分别适用于两种情况的图
- 稠密图,使用
朴素的Dijkstra算法
,其中稠密图的定义是,边的数量级与
o ( n 2 ) o(n^2) o(n2)相当的图,朴素的Dijkstra算法
的时间复杂度是 o ( n 2 ) o(n^2) o(n2),其中n
是图的节点的数量
- 稀疏图,使用
堆优化的Dijkstra算法
,算法的时间复杂度是 o ( m l o g m ) o(mlogm) o(mlogm)其中,m
是边的数量,如果输入的稠密图,那么使用堆优化的Dijkstra
算法的时间复杂度是 o ( n 2 l o g n ) o(n^2logn) o(n2logn)
朴素的Dijkstras
算法的模版
edge = [[float('inf')]*n for n in range(n)]
dis = [float('inf')]*n
dis[k] = 0
done = [False]*n
while True:
x = -1
for i,ok in enumerate(done):
if not ok and (x < 0 or dis[i] < dis[x]):
x = i
if x < 0:
return dis
if dis[x] == float('inf'):
return -1
done[x] = True
for j,d in enumerate(edge[x]):
dis[j] = min(dis[j],dis[j]+d)
使用堆优化的Dijkstra算法
import heapq
class Solution:
def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
edge = [[] for _ in range(n)]
for x,y,z in times:
edge[x-1].append((y-1,z))
dis = [float('inf')]*n
dis[k-1] = 0
h = [(0,k-1)]
while h:
dx,x = heapq.heappop(h)
if dx > dis[x]:
continue
for y,d in edge[x]:
new_dis = dx + d
if new_dis < dis[y]:
dis[y] = new_dis
heapq.heappush(h,(new_dis,y))
mx = max(dis)
return mx if mx < float('inf') else -1
题目
743.网络延迟时间
743.网络延迟时间


思路分析:
由于边的数量远远大于节点的数量,所以我们还是考虑使用稠密图下的朴素的Dijkstra算法
,最后返回不是无穷的最大的路径即可
class Solution:
def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
edge = [[float('inf')]*(n) for _ in range(n)]
for e in times:
edge[e[0]-1][e[1]-1] = e[2]
dis = [float('inf')]*n
ans = dis[k-1] = 0
done = [False] * n
while True:
x = -1
for i,ok in enumerate(done):
if not ok and (x<0 or dis[i] < dis[x]):
x = i
if x < 0 :
return ans
if dis[x] == float('inf'):
return -1
ans = dis[x]
done[x] = True
for y,d in enumerate(edge[x]):
dis[y] = min(dis[y],dis[x]+d)
使用堆优化的解法
import heapq
class Solution:
def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
edge = [[] for _ in range(n)]
for x,y,z in times:
edge[x-1].append((y-1,z))
dis = [float('inf')]*n
dis[k-1] = 0
h = [(0,k-1)]
while h:
dx,x = heapq.heappop(h)
if dx > dis[x]:
continue
for y,d in edge[x]:
new_dis = dx + d
if new_dis < dis[y]:
dis[y] = new_dis
heapq.heappush(h,(new_dis,y))
mx = max(dis)
return mx if mx < float('inf') else -1
3341.到达最后一个房间的最少时间I
3341.到达最后一个房间的最少时间I

思路分析:
开始的时候,我错误的以为题目中只能向右或者向下运动, 所以写了一个动态规划
进行求解,实际上,这个思路是错误的,不过要是只能向下或者向右运动的话,动态规划
也是一种很好的做法
import heapq
class Solution:
def minTimeToReach(self, moveTime: List[List[int]]) -> int:
n = len(moveTime)
m = len(moveTime[0])
dp = [[float('inf')]*(m+1) for _ in range(n+1)]
dp[1][1] = 0
for i in range(n):
for j in range(m):
if i == 0 and j == 0:
continue
dp[i+1][j+1] = min(max(dp[i][j+1],moveTime[i][j])+1,max(dp[i+1][j],moveTime[i][j])+1)
for i in dp:
print(i )
return dp[n][m]
正确的思路:
应该是使用Dijkstra算法
,不过开始的时候,我有点纠结这个edge
也就是边的矩阵如何转化为邻接矩阵或者邻接表
,后面一想,还是我的固定思维阻碍了我,邻接矩阵和邻接表
只是一个工具,帮助我们找到当前的节点的邻居,但是在现在的图中,你通过坐标的加减不就可以得到对应的邻居嘛!
import heapq
class Solution:
def minTimeToReach(self, moveTime: List[List[int]]) -> int:
n,m = len(moveTime),len(moveTime[0])
dis = [[float('inf')]*m for _ in range(n)]
dis[0][0] = 0
done = [[False]*m for _ in range(n)]
while True:
x,y = -1,-1
for i in range(n):
for j in range(m):
if not done[i][j] and ((x<0 and y <0) or dis[i][j] < dis[x][y]):
x,y = i,j
if x<0 and y <0:
return dis[n-1][m-1]
done[x][y] = True
for i,j in (x+1,y),(x-1,y),(x,y+1),(x,y-1):
if 0<= i < n and 0<= j < m:
dis[i][j] = min(max(dis[x][y],moveTime[i][j]) + 1,dis[i][j])
import heapq
class Solution:
def minTimeToReach(self, moveTime: List[List[int]]) -> int:
n,m = len(moveTime),len(moveTime[0])
dis = [[float('inf')]*m for _ in range(n)]
dis[0][0] = 0
h = [(0,0,0)]
while True:
d,x,y = heapq.heappop(h)
if x == n-1 and y == m-1:
return d
if d > dis[x][y]:
continue
for i,j in (x+1,y),(x-1,y),(x,y+1),(x,y-1):
if 0<= i <n and 0<= j < m:
new_dis = max(d,moveTime[i][j])+1
if dis[i][j]>new_dis:
dis[i][j] = new_dis
heapq.heappush(h,(dis[i][j],i,j))