126. Word Ladder II

问题:

给定StartWord和EndWord,在给定的dict中寻找每次值变换一个字母,最终从StartWord能够推移到EndWord的所有最短序列。

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找到路径关系:

1.引入队列q,保存每一步的所有展开结果。在每一步的结尾,用q去替换掉目标队列queue

即从queue一次读取,处理,将结果保存至q,再用q去替换掉queue。

2.每一次的处理:

首先从已经处理过得到的新queue中的元素,从dict中删除。(由于得到queue的方法,即是dict中存在,则保存至queue)

然后遍历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 };
原文地址:https://www.cnblogs.com/habibah-chang/p/12743884.html