题目描述
(困难)字典 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。
解题思路
这就是图的困难题吗?我不理解!
整体思路上和我之前的文章【433.最小基因变化】如出一辙,甚至比其还要简单,本质上就是一道模板题!
从begin
开始广度优先搜索,遇到end
或队列为空时结束,wordlist[]
为合法结点,一次只能变化一个字母,需要考虑状态去重,符合条件的放入队列。思路基本上就是这,下面直接上代码,揭开其虚伪的“困难”面纱。
代码实现
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
//合法结点集合
unordered_set<string> wlist;
//考虑去重
unordered_set<string> visited;
for(string s : wordList){
wlist.insert(s);
}
//目标结点本身非法,直接退出!
if(!wlist.count(endWord)) return 0;
queue<string> que;
que.push(beginWord);
visited.insert(beginWord);
int ans = 1;
//广度优先搜索模板
while(!que.empty()){
int size = que.size();
while(size--){
string temp = que.front();
que.pop();
if(temp == endWord) return ans;
for(int i = 0; i < temp.size(); i++){
string s = temp;
//遍历所有可能存在的变化,26个英文字母
for(int j = 0; j < 26; j++){
//注意 + 'a',转换到小写字母的ASCII码
s[i] = 'a' + j;
if(wlist.count(s) && !visited.count(s)){
que.push(s);
visited.insert(s);
}
}
}
}
ans++;
}
return 0;
}
};