一、题目描述
字典 wordList
中从单词 beginWord
和 endWord
的转换序列是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk
:
- 每一对相邻的单词只差一个字母。
- 对于
1 <= i <= k
时,每个si
都在wordList
中。注意,beginWord
不需要在wordList
中。 sk == endWord
。
给你两个单词 beginWord
和 endWord
和一个字典 wordList
,返回从 beginWord
到 endWord
的最短转换序列中的单词数目 。如果不存在这样的转换序列,返回 0
。
示例 1:
输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出:5
解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。
示例 2:
输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出:0
解释:endWord "cog" 不在字典中,所以无法进行转换。
二、题解
class Solution {
public:
int ladderLength(string begin_word, string end_word, vector<string> &word_list) {
unordered_set<string> word_set(word_list.begin(), word_list.end()); // 通过set提高查找效率
deque<string> word_queue; // 广度优先队列
unordered_map<string, int> word_map; // 存储队列中的单词和其与begin_word的距离
/* end_word不在wordList中,一定无法转化成功 */
// if (word_set.find(end_word) == word_set.end()) {
// return 0;
// }
word_queue.emplace_back(begin_word);
word_map.emplace(begin_word, 1);
while(!word_queue.empty()) {
/* 从队列中取出当前需要处理的单词 */
string cur_word = word_queue.front();
word_queue.pop_front();
/* 已经转化出end_word */
if (cur_word == end_word) {
return word_map.at(cur_word);
}
/* 依次修改cur_word的每一个字母以实现广度优先遍历 */
string tmp_word = cur_word;
for (char &c : tmp_word) {
for (int offset = 0; offset < 26; offset++) {
c = 'a' + offset;
if (word_set.find(tmp_word) != word_set.end() && word_map.find(tmp_word) == word_map.end()) { // 遇到与cur_word相邻且位于字典的单词,同时该单词没有被遍历过
word_map.emplace(tmp_word, word_map.at(cur_word) + 1);
word_queue.emplace_back(tmp_word);
}
}
/* 复原单词 */
tmp_word = cur_word;
}
}
return 0;
}
};