Skip to content

Commit baabc5c

Browse files
committed
added bidirectional BFS
1 parent 4d865ef commit baabc5c

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

basic_algorithm/graph/bfs_dfs.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,5 @@ class Solution:
228228
bfs.append((next_state, next_step))
229229
step += 1
230230
return -1
231-
```
231+
```
232+

basic_algorithm/graph/shortest_path.md

+70-1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,75 @@ class Solution:
110110
flip += 1
111111
```
112112

113+
## Bidrectional BFS
114+
115+
当求点对点的最短路径时,BFS遍历结点数目随路径长度呈指数增长,为缩小遍历结点数目可以考虑从起点 BFS 的同时从终点也做 BFS,当路径相遇时得到最短路径。
116+
117+
### [word-ladder](https://leetcode-cn.com/problems/word-ladder/)
118+
119+
```Python
120+
class Solution:
121+
def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
122+
123+
N, K = len(wordList), len(beginWord)
124+
125+
find_end = False
126+
for i in range(N):
127+
if wordList[i] == endWord:
128+
find_end = True
129+
break
130+
131+
if not find_end:
132+
return 0
133+
134+
wordList.append(beginWord)
135+
N += 1
136+
137+
# clustering nodes for efficiency compare to adjacent list
138+
cluster = collections.defaultdict(list)
139+
for i in range(N):
140+
node = wordList[i]
141+
for j in range(K):
142+
cluster[node[:j] + '*' + node[j + 1:]].append(node)
143+
144+
# bidirectional BFS
145+
visited_start, visited_end = set([beginWord]), set([endWord])
146+
bfs_start, bfs_end = collections.deque([beginWord]), collections.deque([endWord])
147+
step = 2
148+
while bfs_start and bfs_end:
149+
150+
# start
151+
num_level = len(bfs_start)
152+
while num_level > 0:
153+
node = bfs_start.popleft()
154+
for j in range(K):
155+
key = node[:j] + '*' + node[j + 1:]
156+
for n in cluster[key]:
157+
if n in visited_end: # if meet, route from start larger by 1 than route from end
158+
return step * 2 - 2
159+
if n not in visited_start:
160+
visited_start.add(n)
161+
bfs_start.append(n)
162+
num_level -= 1
163+
164+
# end
165+
num_level = len(bfs_end)
166+
while num_level > 0:
167+
node = bfs_end.popleft()
168+
for j in range(K):
169+
key = node[:j] + '*' + node[j + 1:]
170+
for n in cluster[key]:
171+
if n in visited_start: # if meet, route from start equals route from end
172+
return step * 2 - 1
173+
if n not in visited_end:
174+
visited_end.add(n)
175+
bfs_end.append(n)
176+
num_level -= 1
177+
step += 1
178+
179+
return 0
180+
```
181+
113182
## Dijkstra's Algorithm
114183

115184
用于求解单源最短路径问题。思想是 greedy 构造 shortest path tree (SPT),每次将当前距离源点最短的不在 SPT 中的结点加入SPT,与构造最小生成树 (MST) 的 Prim's algorithm 非常相似。可以用 priority queue (heap) 实现。
@@ -178,7 +247,7 @@ class Solution:
178247
return -1
179248
```
180249

181-
## A* Algorithm
250+
## 补充:A* Algorithm
182251

183252
当需要求解有目标的最短路径问题时,BFS 或 Dijkstra's algorithm 可能会搜索过多冗余的其他目标从而降低搜索效率,此时可以考虑使用 A* algorithm。原理不展开,有兴趣可以自行搜索。实现上和 Dijkstra’s algorithm 非常相似,只是优先级需要加上一个到目标点距离的估值,这个估值严格小于等于真正的最短距离时保证得到最优解。当 A* algorithm 中的距离估值为 0 时 退化为 BFS 或 Dijkstra’s algorithm。
184253

0 commit comments

Comments
 (0)