127.单词接龙
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
以下两种方法最主要:注意word
加入队列后,立马将其从集合set
中删除,不然,会继续重复while
循环。
把beginword
作为根节点,改变一个字符形成的新单词 newworld
,如果在set
里面,那就表明能beginword ---- newword
之间形成一条边。那么beginword
的另一端就是其子节点,因此这是一个广度优先呀;
解法一:广度优先I
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> uset(wordList.begin(), wordList.end());
if (uset.find(endWord) == uset.end()) return 0;
queue<string> pq;
pq.push(beginWord);
uset.erase(beginWord);
int ladder = 1;
while (!pq.empty()) {
int n = pq.size();
for (int i = 0; i < n; i++) {
string word = pq.front();
pq.pop();
if (word == endWord) {
return ladder;
}
for (int j = 0; j < word.size(); j++) {
char c = word[j];
for (int k = 0; k < 26; k++) {
word[j] = 'a' + k;
if (uset.find(word) != uset.end()) {
pq.push(word);
uset.erase(word);
}
}
word[j] = c;
}
}
ladder++;
}
return 0;
}
};
解法二:广度优先II
class Solution{
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList){
unordered_set<string> uset(wordList.begin(), wordList.end());
queue<pair<string, int>> q;
q.push({beginWord, 1});
uset.erase(beginWord);
while (!q.empty()){
if (q.front().first == endWord){
return (q.front().second);
}
string word = q.front().first;
int step = q.front().second;
q.pop();
for (int i = 0; i < word.size(); i++){
char ch = word[i];
for (int j = 0; j < 26; j++){
word[i] = 'a' + j;
if (uset.find(word) != uset.end()){
q.push({word, step+1});
uset.erase(word) ;
}
word[i] = ch;
}
}
}
return 0;
}
};