• 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 };
  • 相关阅读:
    Codeforces Round #436 (Div. 2)
    【bzoj1090】 [SCOI2003]字符串折叠
    【并查集】食物链(带权并查集)
    【图论】二分图
    【图论】关押罪犯
    关于图论的若干巴拉巴拉
    一系列的入门and一堆吐槽
    【分块】八
    9-30刷题记录
    bzoj5055
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/12743884.html
Copyright © 2020-2023  润新知