1,题目要求
Given two words (beginWord and endWord), and a dictionary’s word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
Only one letter can be changed at a time.
Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
Note:
- Return 0 if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
- You may assume no duplicates in the word list.
- You may assume beginWord and endWord are non-empty and are not the same.
Example 1:
Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
Output: 5
Explanation: As one shortest transformation is “hit” -> “hot” -> “dot” -> “dog” -> “cog”,
return its length 5.
Example 2:
Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Output: 0
Explanation: The endWord “cog” is not in wordList, therefore no possible transformation.
给定两个单词(beginWord和endWord)和一个字典的单词列表,找到从beginWord到endWord的最短变换序列的长度,这样:
- 一次只能更改一个字母。
- 每个转换后的单词必须存在于单词列表中。 请注意,beginWord不是转换后的单词。
注意:
- 如果没有这样的转换序列,则返回0。
- 所有单词都有相同的长度。
- 所有单词仅包含小写字母字符。
- 您可以假设单词列表中没有重复项。
- 您可能认为beginWord和endWord是非空的并且不相同。
2,题目思路
对于这道题,要求将一个单词按照字典转化为另一个单词。
在这个单词转化为题上,有两个条件:首先,每次只能转换一个字符;其次,转换的单词必须要出现在给定的字典中。
在解决这个问题上,实际上这是一个BFS问题:
从beginWord出发,然后访问它的邻居——出现在dict中并且只改变一个字符的单词,然后,访问这些邻居中尚未访问的邻居,直到访问到endWord位置。
同时,BFS的解决上,我们可以从两端同时开始出发,同时从beginWord和endWord出发,当二者相遇,自然是找到了最终的结果。
3,代码实现
static auto speedup = [](){
ios::sync_with_stdio(false);
cin.tie(nullptr);
return nullptr;
}();
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> dict(wordList.begin(),wordList.end()), head, tail, *pHead, *pTail;
if(dict.find(endWord) == dict.end()) //没找到这个单词
return 0;
head.insert(beginWord);
tail.insert(endWord);
int ladder = 2;
while(!head.empty() && !tail.empty()){
//让pHead指向长度较小的set,用于遍历
//让pTail指向长度较大的set,用于搜索
if(head.size() < tail.size()){
pHead = &head;
pTail = &tail;
}
else{
pHead = &tail;
pTail = &head;
}
unordered_set<string> tmp;
for(auto it = pHead->begin();it!=pHead->end();it++){
string word = *it;
for(int i = 0;i<word.size();i++){
//依次更改word中的字符,判断是否在dict中
char origin = word[i];
for(int j = 0;j<26;j++){
word[i] = 'a' + j; //a~z
//两集合相遇,即找到了转换方法
if(pTail->find(word) != pTail->end())
return ladder;
//没相遇,但是当前单词在dict中,则将这个转换加入候选以供下一次寻找
if(dict.find(word) != dict.end()){
tmp.insert(word);
dict.erase(word); //已经遍历过dict中的单词,需要删除
}
}
word[i] = origin; //恢复,以供下一个字符变化的遍历
}
}
ladder++;
pHead->swap(tmp); //swap是替换,将当期head换为tmp
}
return 0;
}
};