@@ -68,7 +68,7 @@ Tag : 「双向 BFS」
6868
6969** 随着层数的加深,这个数字的增速越快,这就是「搜索空间爆炸」问题。**
7070
71- ![ ] ( https://pic.leetcode-cn.com/1623894968-XELIvK-image.png )
71+ ![ image.png ] ( https://pic.leetcode-cn.com/1623894968-XELIvK-image.png )
7272
7373** 在朴素的 BFS 实现中,空间的瓶颈主要取决于搜索空间中的最大宽度。**
7474
@@ -78,7 +78,7 @@ Tag : 「双向 BFS」
7878
7979** 同时从两个方向开始搜索,一旦搜索到相同的值,意味着找到了一条联通起点和终点的最短路径。**
8080
81- ![ ] ( https://pic.leetcode-cn.com/1623894976-CCMljJ-image.png )
81+ ![ image.png ] ( https://pic.leetcode-cn.com/1623894976-CCMljJ-image.png )
8282
8383「双向 BFS」的基本实现思路如下:
8484
@@ -212,6 +212,79 @@ class Solution {
212212
213213---
214214
215+ ### 【补充】启发式搜索 AStar
216+
217+ 可以直接根据本题规则来设计 A* 的「启发式函数」。
218+
219+ 比如对于两个字符串 ` a ` ` b ` 直接使用它们不同字符的数量来充当估值距离,我觉得是合适的。
220+
221+ 因为不同字符数量的差值可以确保不会超过真实距离(是一个理论最小替换次数)。
222+
223+ 注意:本题数据比较弱,用 A* 过了,但通常我们需要「确保有解」,A* 的启发搜索才会发挥真正价值。而本题,除非 ` endWord ` 本身就不在 ` wordList ` 中,其余情况我们无法很好提前判断「是否有解」。这时候 A* 将不能带来「搜索空间的优化」,效果不如「双向 BFS」。
224+
225+ 代码:
226+ ``` Java []
227+ class Solution {
228+ class Node {
229+ String str;
230+ int val;
231+ Node (String _str , int _val ) {
232+ str = _str;
233+ val = _val;
234+ }
235+ }
236+ String s, e;
237+ int INF = 0x3f3f3f3f ;
238+ Set<String > set = new HashSet<> ();
239+ public int ladderLength (String _s , String _e , List<String > ws ) {
240+ s = _s;
241+ e = _e;
242+ for (String w : ws) set. add(w);
243+ if (! set. contains(e)) return 0 ;
244+ int ans = astar();
245+ return ans == - 1 ? 0 : ans + 1 ;
246+ }
247+ int astar () {
248+ PriorityQueue<Node > q = new PriorityQueue<> ((a,b)- > a. val- b. val);
249+ Map<String , Integer > dist = new HashMap<> ();
250+ dist. put(s, 0 );
251+ q. add(new Node (s, f(s)));
252+
253+ while (! q. isEmpty()) {
254+ Node poll = q. poll();
255+ String str = poll. str;
256+ int distance = dist. get(str);
257+ if (str. equals(e)) {
258+ break ;
259+ }
260+ int n = str. length();
261+ for (int i = 0 ; i < n; i++ ) {
262+ for (int j = 0 ; j < 26 ; j++ ) {
263+ String sub = str. substring(0 , i) + String . valueOf((char )(' a' + j)) + str. substring(i + 1 );
264+ if (! set. contains(sub)) continue ;
265+ if (! dist. containsKey(sub) || dist. get(sub) > distance + 1 ) {
266+ dist. put(sub, distance + 1 );
267+ q. add(new Node (sub, dist. get(sub) + f(sub)));
268+ }
269+ }
270+ }
271+ }
272+ return dist. containsKey(e) ? dist. get(e) : - 1 ;
273+ }
274+ int f (String str ) {
275+ if (str. length() != e. length()) return INF ;
276+ int n = str. length();
277+ int ans = 0 ;
278+ for (int i = 0 ; i < n; i++ ) {
279+ ans += str. charAt(i) == e. charAt(i) ? 0 : 1 ;
280+ }
281+ return ans;
282+ }
283+ }
284+ ```
285+
286+ ---
287+
215288### 最后
216289
217290这是我们「刷穿 LeetCode」系列文章的第 ` No.127 ` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先将所有不带锁的题目刷完。
0 commit comments