@@ -105,14 +105,84 @@ class Solution:
105
105
for dr, dc in neighors:
106
106
nr, nc = r + dr, c + dc
107
107
if 0 <= nr < M and 0 <= nc < N:
108
- if A[nr][nc] == 0 : # meet and edge
108
+ if A[nr][nc] == 0 :
109
109
A[nr][nc] = - 2
110
110
bfs.append((nr, nc))
111
111
elif A[nr][nc] == 1 :
112
112
return flip
113
113
flip += 1
114
114
```
115
115
116
+ ## Dijkstra's Algorithm
117
+
118
+ 用于求解单源最短路径问题。思想是 greedy 构造 shortest path tree (SPT),每次将当前距离源点最短的不在 SPT 中的结点加入SPT,与构造最小生成树 (MST) 的 Prim's algorithm 非常相似。可以用 priority queue (heap) 实现。
119
+
120
+ ### [ network-delay-time] ( https://leetcode-cn.com/problems/network-delay-time/ )
121
+
122
+ 标准的单源最短路径问题,使用朴素的的 Dijikstra 算法即可,可以当成模板使用。
123
+
124
+ ``` Python
125
+ class Solution :
126
+ def networkDelayTime (self , times : List[List[int ]], N : int , K : int ) -> int :
127
+
128
+ # construct graph
129
+ graph_neighbor = collections.defaultdict(list )
130
+ for s, e, t in times:
131
+ graph_neighbor[s].append((e, t))
132
+
133
+ # Dijkstra
134
+ SPT = {}
135
+ min_heap = [(0 , K)]
136
+
137
+ while min_heap:
138
+ delay, node = heapq.heappop(min_heap)
139
+ if node not in SPT :
140
+ SPT [node] = delay
141
+ for n, d in graph_neighbor[node]:
142
+ if n not in SPT :
143
+ heapq.heappush(min_heap, (d + delay, n))
144
+
145
+ return max (SPT .values()) if len (SPT ) == N else - 1
146
+ ```
147
+
148
+ ### [ cheapest-flights-within-k-stops] ( https://leetcode-cn.com/problems/cheapest-flights-within-k-stops/ )
149
+
150
+ 在标准的单源最短路径问题上限制了路径的边数,因此需要同时维护当前 SPT 内每个结点最短路径的边数,当遇到边数更小的路径 (边权和可以更大) 时结点需要重新入堆,以更新后继在边数上限内没达到的结点。
151
+
152
+ ``` Python
153
+ class Solution :
154
+ def findCheapestPrice (self , n : int , flights : List[List[int ]], src : int , dst : int , K : int ) -> int :
155
+
156
+ # construct graph
157
+ graph_neighbor = collections.defaultdict(list )
158
+ for s, e, p in flights:
159
+ graph_neighbor[s].append((e, p))
160
+
161
+ # modified Dijkstra
162
+ prices, steps = {}, {}
163
+ min_heap = [(0 , 0 , src)]
164
+
165
+ while len (min_heap) > 0 :
166
+ price, step, node = heapq.heappop(min_heap)
167
+
168
+ if node == dst: # early return
169
+ return price
170
+
171
+ if node not in prices:
172
+ prices[node] = price
173
+
174
+ steps[node] = step
175
+ if step <= K:
176
+ step += 1
177
+ for n, p in graph_neighbor[node]:
178
+ if n not in prices or step < steps[n]:
179
+ heapq.heappush(min_heap, (p + price, step, n))
180
+
181
+ return - 1
182
+ ```
183
+
184
+ ## 补充
185
+
116
186
## Bidrectional BFS
117
187
118
188
当求点对点的最短路径时,BFS遍历结点数目随路径长度呈指数增长,为缩小遍历结点数目可以考虑从起点 BFS 的同时从终点也做 BFS,当路径相遇时得到最短路径。
@@ -182,81 +252,13 @@ class Solution:
182
252
return 0
183
253
```
184
254
185
- ## Dijkstra's Algorithm
186
-
187
- 用于求解单源最短路径问题。思想是 greedy 构造 shortest path tree (SPT),每次将当前距离源点最短的不在 SPT 中的结点加入SPT,与构造最小生成树 (MST) 的 Prim's algorithm 非常相似。可以用 priority queue (heap) 实现。
188
-
189
- ### [ network-delay-time] ( https://leetcode-cn.com/problems/network-delay-time/ )
190
-
191
- 标准的单源最短路径问题,使用朴素的的 Dijikstra 算法即可,可以当成模板使用。
192
-
193
- ``` Python
194
- class Solution :
195
- def networkDelayTime (self , times : List[List[int ]], N : int , K : int ) -> int :
196
-
197
- # construct graph
198
- graph_neighbor = collections.defaultdict(list )
199
- for s, e, t in times:
200
- graph_neighbor[s].append((e, t))
201
-
202
- # Dijkstra
203
- SPT = {}
204
- min_heap = [(0 , K)]
205
-
206
- while min_heap:
207
- delay, node = heapq.heappop(min_heap)
208
- if node not in SPT :
209
- SPT [node] = delay
210
- for n, d in graph_neighbor[node]:
211
- if n not in SPT :
212
- heapq.heappush(min_heap, (d + delay, n))
213
-
214
- return max (SPT .values()) if len (SPT ) == N else - 1
215
- ```
216
-
217
- ### [ cheapest-flights-within-k-stops] ( https://leetcode-cn.com/problems/cheapest-flights-within-k-stops/ )
218
-
219
- 在标准的单源最短路径问题上限制了路径的边数,因此需要同时维护当前 SPT 内每个结点最短路径的边数,当遇到边数更小的路径 (边权和可以更大) 时结点需要重新入堆,以更新后继在边数上限内没达到的结点。
220
-
221
- ``` Python
222
- class Solution :
223
- def findCheapestPrice (self , n : int , flights : List[List[int ]], src : int , dst : int , K : int ) -> int :
224
-
225
- # construct graph
226
- graph_neighbor = collections.defaultdict(list )
227
- for s, e, p in flights:
228
- graph_neighbor[s].append((e, p))
229
-
230
- # modified Dijkstra
231
- prices, steps = {}, {}
232
- min_heap = [(0 , 0 , src)]
233
-
234
- while len (min_heap) > 0 :
235
- price, step, node = heapq.heappop(min_heap)
236
-
237
- if node == dst: # early return
238
- return price
239
-
240
- if node not in prices:
241
- prices[node] = price
242
-
243
- steps[node] = step
244
- if step <= K:
245
- step += 1
246
- for n, p in graph_neighbor[node]:
247
- if n not in prices or step < steps[n]:
248
- heapq.heappush(min_heap, (p + price, step, n))
249
-
250
- return - 1
251
- ```
252
-
253
- ## 补充:A* Algorithm
255
+ ## A* Algorithm
254
256
255
257
当需要求解有目标的最短路径问题时,BFS 或 Dijkstra's algorithm 可能会搜索过多冗余的其他目标从而降低搜索效率,此时可以考虑使用 A* algorithm。原理不展开,有兴趣可以自行搜索。实现上和 Dijkstra’s algorithm 非常相似,只是优先级需要加上一个到目标点距离的估值,这个估值严格小于等于真正的最短距离时保证得到最优解。当 A* algorithm 中的距离估值为 0 时 退化为 BFS 或 Dijkstra’s algorithm。
256
258
257
259
### [ sliding-puzzle] ( https://leetcode-cn.com/problems/sliding-puzzle )
258
260
259
- 思路 1:BFS。为了方便对比 A* 算法写成了与其相似的形式。
261
+ - 方法 1:BFS。为了方便对比 A* 算法写成了与其相似的形式。
260
262
261
263
``` Python
262
264
class Solution :
@@ -300,7 +302,7 @@ class Solution:
300
302
return - 1
301
303
```
302
304
303
- 思路 2:A* algorithm
305
+ - 方法 2:A* algorithm
304
306
305
307
``` Python
306
308
class Solution :
0 commit comments