# 单词接龙(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;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21