1.BFS
借助队列,存在每一次搜索的字符串
首先将BeginWord入队,队列不为空时,判断当前队列的大小,依次取出队列中的元素,在wordList中寻找与其差一个字符的字符串,将找到的字符串入队,且wordList中找到的字符串设为空,之后不在搜索该字符串
最短路径,即找到endword所需的BFS的层数
代码如下:
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
queue<string> qu;
qu.push(beginWord);
int res = 0;
while(!qu.empty()){
res++;
for(int size = qu.size(); size > 0; size--){
string front = qu.front();
if(front == endWord) return res;//已经找到,则返回
qu.pop();
for(auto & w: wordList){
if(w.empty() || w.size() != beginWord.size()) continue;
int diff = 0;
for(int i = 0; i < w.size(); i++){
if(w[i] != front[i]) ++diff;
if(diff > 1) break;
}
if(diff <= 1){//wordList中可能存在和begin相同的字符串
qu.push(w);
w = "";
}
}
}
}
return 0;
}
};
2.双端BFS
即一端从beginWord到endWord,一端从endWord到beginWord
如比如从beginword到endword距离是10,从endword到beginword距离是3,则选择从endword到beginword的路径
每次搜索从中间结果较少的一端出发,可以省略很多不必要的搜索过程
代码如下:
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> wordSet{wordList.begin(), wordList.end()};
if(wordSet.find(endWord) == wordSet.end()) return 0;//wordList中不存在endWord
int res = 1;
unordered_set<string> beginSet{beginWord};
unordered_set<string> endSet{endWord};
while(!beginSet.empty()){
res++;
unordered_set<string> nextSet;//存储与beginSet中差一个字符的字符串
for(auto & word : beginSet) {
wordSet.erase(word);//已经找到的从wordSet中删除,之后不再判断该字符串
}
for(auto & word: beginSet){//遍历beginSet中每一个字符串
for(int i = 0; i < word.size(); i++){
string nextWord = word;
for(char j = 'a'; j <= 'z'; j++){
nextWord[i] = j;//替换beginSet中word字符串中的某一个字符,nextWord与word只差一个字符
if(endSet.find(nextWord) != endSet.end()) return res;
if(wordSet.find(nextWord) != wordSet.end()){
nextSet.insert(nextWord);
}
}
}
}
beginSet = nextSet;
if(beginSet.size() > endSet.size()){
swap(beginSet, endSet);
}
}
return 0;
}
};