# 单词接龙(127)
# 题目
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
- 每次转换只能改变一个字母。
- 转换过程中的中间单词必须是字典中的单词。
# 说明
- 如果不存在这样的转换序列,返回 0。
- 所有单词具有相同的长度。
- 所有单词只由小写字母组成。
- 字典中不存在重复的单词。
- 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
# 示例
输入:
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
# 算法
# 广度优先搜索(BFS)
本题要求最短转换序列
,看到最短
首先想到广度优先搜索
- 思路:
将需要变换的词(初始为startWord
)保存在一个队列中,将队列头部的词改变一位字母后去字典中匹配,如果匹配到结果,即说明这个变换可能是最短结果中的一步,将这个结果保存在队列尾,防止重复匹配将这个结果从字典中删除,如果变换后在字典中匹配到的词是endWord
,那么返回其匹配过的次数(最先返回的就是最短次数)
- 实现:
使用wordSet
保存字典;使用队列queue
保存需要被匹配的(需要变换一个字母以匹配字典中的)单词
只要队列queue
中还有需要被匹配的单词,就继续查找,否则返回0
匹配失败
每次开始匹配时取出队列queue
中的第一个词及他已经匹配过的次数,先检查这个词是否是endWord
,如果是直接返回匹配次数level
如果不是endWord
,那么将其每一位依次试着变换成其他的字母,然后在字典wordSet
中查找是否有匹配的结果:如果没有则抛弃这个新组合的词;如果匹配到这个新组合的词,那么说明可能是一个转换路径上的词,那么将这个词和他匹配过的次数level+1
一起推入队列queue
尾部,然后为了防止重复匹配,将这个词从字典wordSet
中删除
export const ladderLength = (beginWord, endWord, wordList) => {
const wordSet = new Set(wordList);
const queue = [[beginWord, 1]];
while (queue.length) {
const [curWord, level] = queue.shift();
if (curWord === endWord) {
return level;
}
for (let i = 0; i < curWord.length; i++) {
for (let j = "a".charCodeAt(); j <= "z".charCodeAt(); j++) {
const maybeNextWord = curWord.slice(0, i) + String.fromCharCode(j) + curWord.slice(i + 1);
if (wordSet.has(maybeNextWord)) {
queue.push([maybeNextWord, level + 1]);
wordSet.delete(maybeNextWord);
}
}
}
}
return 0;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21