理论
解决的问题
在朴素的 BFS 实现中,空间的瓶颈主要取决于搜索空间中的最大宽度。
解决的方法
同时从两个方向开始搜索,一旦搜索到相同的值,意味着找到了一条联通起点和终点的最短路径。
实现的基本思路
- 创建「两个队列」分别用于两个方向的搜索;
- 创建「两个哈希表」用于表示「访问过的节点」;
- 为了尽可能让两个搜索方向“平均”,每次从队列中取值进行扩展时,先判断哪个队列容量较少,队列数据较少的先执行;
- 如果在搜索过程中「搜索到对方搜索过的节点」,说明找到了最短路径;如果结束搜索过程后,还没有找到,表示不连通。
算法实践
问题描述
字典 wordList
中从单词 beginWord
和 endWord
的 转换序列
是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk
:
每一对相邻的单词只差一个字母。
对于 1 <= i <= k
时,每个 si
都在 wordList
中。注意, beginWord
不需要在 wordList
中。
sk == endWord
给你两个单词 beginWord
和 endWord
和一个字典 wordList
,返回 从 beginWord
到 endWord
的 最短转换序列 中的 单词数目
。如果不存在这样的转换序列,返回 0
。
示例
输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出:5
解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。
输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出:0
解释:endWord "cog" 不在字典中,所以无法进行转换。
解题思路
- 先判断
endWord
是否在wordList
中,如果不在,直接返回0
; - 创建两个队列分别表示2个方向的搜索;
- 对两个队列进行bfs,优先跑队列长度小的队列;
- 当搜索过程中「搜索到对方搜索过的节点」,返回搜索次数。
代码示例(JAVA)
class Solution {
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
Set<String> wordSet = new HashSet<>();
for (String word : wordList) {
wordSet.add(word);
}
if (!wordList.contains(endWord)) {
return 0;
}
Set<String> startSet = new HashSet<>();
Set<String> endSet = new HashSet<>();
Set<String> visited = new HashSet<>();
startSet.add(beginWord);
endSet.add(endWord);
int len = 1;
while (!startSet.isEmpty() && !endSet.isEmpty()) {
// 优先跑少的部分
if (startSet.size() > endSet.size()) {
Set<String> temp = startSet;
startSet = endSet;
endSet = temp;
}
Set<String> temp = new HashSet<>();
for (String word : startSet) {
char[] chars = word.toCharArray();
for (int i = 0; i < chars.length; i++) {
char old = chars[i];
for (char k = 'a'; k <= 'z'; k++) {
if (chars[i] == k) {
continue;
}
chars[i] = k;
String newString = String.valueOf(chars);
if (endSet.contains(newString)) {
return len + 1;
}
if (!visited.contains(newString) && wordSet.contains(newString)) {
temp.add(newString);
visited.add(newString);
}
chars[i] = old;
}
}
}
startSet = temp;
len++;
}
return 0;
}
}
网友评论