1. 题目
给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。
转换需遵循如下规则:
- 每次转换只能改变一个字母。
- 转换过程中的中间单词必须是字典中的单词。
说明:
如果不存在这样的转换序列,返回一个空列表。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例 1:
输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
输出:
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
示例 2:
输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
输出: []
解释: endWord "cog" 不在字典中,所以不存在符合要求的转换序列。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-ladder-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
类似题目:
LeetCode 127. 单词接龙(图的BFS/双向BFS)
程序员面试金典 - 面试题 17.22. 单词转换(BFS)
2. BFS解题
- 详见注释
class Solution {
public:
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList)
{
vector<vector<string>> ans;
unordered_set<string> wlist(wordList.begin(),wordList.end());
unordered_set<string> words;//存放当次被加入到路径的单词
queue<vector<string>> q;//队列里存放的是可行的路径
q.push({beginWord});
words.insert(beginWord);
int level = 1, minLevel = INT_MAX, n, i;
vector<string> frontPath, newPath;
string lastWordOfPath, newLastWord;
char ch;
while(!q.empty())
{
n = q.size();
while(n--)
{
frontPath = q.front();//vector<string>
q.pop();//frontPath出队
if(frontPath.size() > level)//下一个level时进入
{
for(string word:words)
wlist.erase(word);//将上一个lv进入路径的单词从集合中删除
words.clear();
level = frontPath.size();//level+1
if(level > minLevel) //如果level比最小的还大,没必要进行下去
break;
}
lastWordOfPath = frontPath.back();
for(i = 0; i < lastWordOfPath.size(); i++)
{ //根据最后一个单词衍生新的单词
newLastWord = lastWordOfPath;
for(ch = 'a'; ch <= 'z'; ch++)
{
newLastWord[i] = ch;
if(!wlist.count(newLastWord)) //新单词不在集合中,下一个
continue;
words.insert(newLastWord);//在集合中,加入路径,并记录在words
newPath = frontPath;//vector<string>
newPath.push_back(newLastWord);
if(newLastWord == endWord)
{
ans.push_back(newPath);
minLevel = level;
}
else
q.push(newPath);
}
}
}
}
return ans;
}
};