問題:數組
給定StartWord和EndWord,在給定的dict中尋找每次值變換一個字母,最終從StartWord可以推移到EndWord的全部最短序列。bash
Example 1: Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"] Output: [ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ] Example 2: Input: beginWord = "hit" endWord = "cog" wordList = ["hot","dot","dog","lot","log"] Output: [] Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
解法1:函數
單向BFS找到路徑關係:spa
1.引入隊列q,保存每一步的全部展開結果。在每一步的結尾,用q去替換掉目標隊列queuecode
即從queue一次讀取,處理,將結果保存至q,再用q去替換掉queue。orm
2.每一次的處理:對象
首先從已經處理過獲得的新queue中的元素,從dict中刪除。(因爲獲得queue的方法,便是dict中存在,則保存至queue)blog
而後遍歷queue的每個word,進行如下處理:遞歸
對word的每個字符,進行a~z字母替換,隊列
判斷:1,若是==endWord,則標記found找到。同時記錄該路徑到children圖中。
2,若是dict中存在,則加入新queue中(這裏是先保存到q,以後在總體和queue替換),同時記錄該路徑關係到children圖中。
構建children圖,key:A字符串,value:B字符串,(由A變化一個字符獲得多種可能的B)
unordered_map<string,vector<string>> children; children[parent].push_back(child);
再經過children圖進行DFS,構建全部path結果數組。
1 vector<string> path={beginWord}; 2 if(found){ 3 getPath(children, beginWord, endWord, path, res); 4 }
DFS 遞歸函數:
1 void getPath(unordered_map<string,vector<string>>& children, string beginWord, string endWord, vector<string>& path, vector<vector<string>>& res) { 2 if(beginWord==endWord){ 3 res.push_back(path); 4 return; 5 } 6 const auto find = children.find(beginWord); 7 if(find==children.end()) return; 8 for(const string child: find->second){ 9 path.push_back(child); 10 getPath(children, child, endWord, path, res); 11 path.pop_back(); 12 } 13 }
解法2:
diff解法1:
雙向 查找路徑關係。每次選取size最短的做爲對象,進行展開查找。
將解法1中的對象隊列queue,改成q1和q2,
若q1短,那麼本次將q1看做queue,q2看做endWord,反之亦然。
所作處理皆同方法1,
只有children的構建,因爲雙向構建,正向處理的狀況下,children構建方法同解法1,
反向處理(由endWord向start推)的狀況下,parent和child對掉。
要斷定是否爲正向,則須要引入變量 backward。
代碼參考:
解法1:
1 class Solution { 2 public: 3 void getPath(unordered_map<string,vector<string>>& children, const string beginWord, const string endWord, vector<string>& path, vector<vector<string>>& res) { 4 if(beginWord==endWord){ 5 res.push_back(path); 6 return; 7 } 8 auto find=children.find(beginWord); 9 if(find==children.end()) return; 10 for(const string& child:find->second){ 11 path.push_back(child); 12 getPath(children, child, endWord, path, res); 13 path.pop_back(); 14 } 15 } 16 17 vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) { 18 vector<vector<string>> res; 19 unordered_set<string> dict(wordList.begin(), wordList.end()); 20 unordered_set<string> queue={beginWord}, p; 21 unordered_map<string,vector<string>> children; 22 bool found=false; 23 if(dict.count(endWord)==0)return res; 24 while(!queue.empty()&&!found){ 25 for(const string& word: queue){ 26 dict.erase(word); 27 } 28 for(const string& word: queue){ 29 string cur=word; 30 for(int j=0; j<=word.length(); j++){ 31 char ch=cur[j]; 32 for(char i='a'; i<='z'; i++){ 33 cur[j]=i; 34 if(cur==endWord){ 35 found=true; 36 children[word].push_back(cur); 37 }else if(dict.count(cur)&&!found){ 38 p.insert(cur);//下一次待檢索 39 children[word].push_back(cur); 40 } 41 } 42 cur[j]=ch; 43 } 44 } 45 swap(queue,p); 46 p.clear(); 47 } 48 vector<string> path={beginWord}; 49 if(found){ 50 getPath(children, beginWord, endWord, path, res); 51 } 52 return res; 53 } 54 };
解法2:
1 class Solution { 2 public: 3 void getPath(unordered_map<string,vector<string>>& children, string beginWord, string endWord, vector<string>& path, vector<vector<string>>& res) { 4 if(beginWord==endWord){ 5 res.push_back(path); 6 return; 7 } 8 const auto find = children.find(beginWord); 9 if(find==children.end()) return; 10 for(const string child: find->second){ 11 path.push_back(child); 12 getPath(children, child, endWord, path, res); 13 path.pop_back(); 14 } 15 } 16 vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) { 17 vector<vector<string>> res; 18 unordered_set<string> dict(wordList.begin(), wordList.end()); 19 unordered_set<string> q1={beginWord}, q2={endWord}; 20 bool backward=false; 21 unordered_map<string,vector<string>> children; 22 bool found=false; 23 if(dict.count(endWord)==0)return res; 24 while(!q1.empty()&&!q2.empty()&&!found){ 25 if(q1.size()>q2.size()){ 26 backward=!backward; 27 swap(q1,q2); 28 } 29 for(const string& word: q1){ 30 dict.erase(word); 31 } 32 for(const string& word: q2){ 33 dict.erase(word); 34 } 35 unordered_set<string> q; 36 for(const string& word: q1){ 37 string cur=word; 38 for(int j=0; j<=word.length(); j++){ 39 char ch=cur[j]; 40 for(char i='a'; i<='z'; i++){ 41 cur[j]=i; 42 if(q2.count(cur)){ 43 found=true; 44 if(!backward){ 45 children[word].push_back(cur); 46 }else{ 47 children[cur].push_back(word); 48 } 49 }else if(dict.count(cur)&&!found){ 50 q.insert(cur);//下一次待檢索 51 if(!backward){ 52 children[word].push_back(cur); 53 }else{ 54 children[cur].push_back(word); 55 } 56 } 57 } 58 cur[j]=ch; 59 } 60 } 61 swap(q1,q); 62 q.clear(); 63 } 64 vector<string> path={beginWord}; 65 if(found){ 66 getPath(children, beginWord, endWord, path, res); 67 } 68 return res; 69 } 70 };