同样思想的升级版【https://www.cnblogs.com/habibah-chang/p/12743884.html】
问题:
给定StartWord和EndWord,在给定的dict中寻找每次值变换一个字母,最终从StartWord能够推移到EndWord的一个序列步数。
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.
解法:
1.基本算法:单向BFS,宽度优先搜索:每次查找完只变化一个字母的所有可能,再进行变换下一个字母的尝试。
建立字典:dict
unordered_set<string> dict(wordList.begin(), wordList.end());
使用queue来记录当前变化第 n 次字母后,需要处理的所有可能。
临时处理队列 q,每次处理过后,将新生成的q去替换处理对象queue,进行下一次处理。
(读取:queue,插入:q)
每一次处理完一遍queue,即是一层展开,所求步数 res++
没处理完一遍queue,将queue里的元素,从dict中删除,排除重复查找同一个word的问题。
参考代码:
1 class Solution { 2 public: 3 int ladderLength(string beginWord, string endWord, vector<string>& wordList) { 4 unordered_set<string> dict(wordList.begin(), wordList.end()); 5 unordered_set<string> queue={beginWord}, q; 6 int res=0; 7 if(dict.count(endWord)==0) return res; 8 while(!queue.empty()){ 9 res++; 10 for(const string& word:queue){ 11 dict.erase(word); 12 } 13 for(const string& word:queue){ 14 string curr = word; 15 for(int i=0; i<word.length(); i++){ 16 char ch=curr[i]; 17 for(char j='a'; j<='z'; j++){ 18 curr[i]=j; 19 if(curr==endWord)return ++res;//【endWord对比操作】 20 else if(dict.count(curr)){ 21 q.insert(curr); 22 } 23 } 24 curr[i]=ch; 25 } 26 } 27 swap(q,queue); 28 q.clear(); 29 } 30 return 0; 31 } 32 };
2.对 1 进行优化:
双向 BFS,
q1={beginWord}
q2={endWord}
每次选择 q1 和 q2 中短的,作为【解法1】的queue。
长的用来替换【解法1】的【endWord对比操作】
参考代码:
1 class Solution { 2 public: 3 int ladderLength(string beginWord, string endWord, vector<string>& wordList) { 4 unordered_set<string> dict(wordList.begin(), wordList.end()); 5 unordered_set<string> q1={beginWord}, q2={endWord}, q; 6 int res=0; 7 if(dict.count(endWord)==0) return res; 8 while(!q1.empty()&&!q2.empty()){ 9 res++; 10 for(const string& word:q1){ 11 dict.erase(word); 12 } 13 for(const string& word:q2){ 14 dict.erase(word); 15 } 16 if(q1.size()>q2.size()){ 17 swap(q1,q2); 18 } 19 for(const string& word:q1){ 20 string curr = word; 21 for(int i=0; i<word.length(); i++){ 22 char ch=curr[i]; 23 for(char j='a'; j<='z'; j++){ 24 curr[i]=j; 25 if(q2.count(curr))return ++res;//【endWord对比操作】 26 else if(dict.count(curr)){ 27 q.insert(curr); 28 } 29 } 30 curr[i]=ch; 31 } 32 } 33 swap(q,q1); 34 q.clear(); 35 } 36 return 0; 37 } 38 };