• LeetCode: Word Ladder


    LeetCode: Word Ladder

    Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:

    1. Only one letter can be changed at a time
    2. Each intermediate word must exist in the dictionary

    For example,

    Given:
    start = "hit"
    end = "cog"
    dict = ["hot","dot","dog","lot","log"]

    As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
    return its length 5.

    Note:

      • Return 0 if there is no such transformation sequence.
      • All words have the same length.
      • All words contain only lowercase alphabetic characters.

    地址:https://oj.leetcode.com/problems/word-ladder/

    算法:从开始字符串开始,用BFS进行搜索,若字符串A可以变换到字符串B,则以字符串B为值的节点为以字符串A为值节点的子节点。注意开始节点为跟,若一个字符串可以为多个字符串的子节点,那么取深度最低的那个节点。代码:

     1 class Solution {
     2 public:
     3     int ladderLength(string start, string end, unordered_set<string> &dict) {
     4         if(start == end)    return 1;
     5         int len = start.size();
     6         map<string,int> depth;
     7         queue<string> Q;
     8         Q.push(start);
     9         depth[start] = 1;
    10         while(!Q.empty()){
    11             string s = Q.front();
    12             if(isChangedOne(s,end)){
    13                 return depth[s] + 1;
    14             }
    15             for(int i = 0; i < len; ++i){
    16                 for(char c = 'a'; c <= 'z'; ++c){
    17                     if(s[i] != c){
    18                         string temp = s;
    19                         temp[i] = c;
    20                         if(dict.find(temp) != dict.end() && depth.find(temp) == depth.end()){
    21                             Q.push(temp);
    22                             depth[temp] = depth[s] + 1;
    23                         }
    24                     }
    25                 }
    26              
    27             }
    28   
    29             Q.pop();
    30         }
    31         
    32         return 0;
    33     }
    34     
    35     bool isChangedOne(const string &a, const string &b){
    36         int num_changed = 0;
    37         for(int i = 0; i < a.size(); ++i){
    38             if(a[i] != b[i])    ++num_changed;
    39             if(2 == num_changed)    break;
    40         }
    41         return 1 == num_changed;
    42     }
    43 };

    第二题:

    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:

    1. Only one letter can be changed at a time
    2. Each intermediate word must exist in the dictionary

    For example,

    Given:
    start = "hit"
    end = "cog"
    dict = ["hot","dot","dog","lot","log"]

    Return

      [
        ["hit","hot","dot","dog","cog"],
        ["hit","hot","lot","log","cog"]
      ]
    

    Note:

      • All words have the same length.
      • All words contain only lowercase alphabetic characters.

    地址:https://oj.leetcode.com/problems/word-ladder-ii/

    算法:这道题自己做的时候一直超时,后来看了网上的答案才通过的。这道题最要难在要把所有从开始字符串到结束字符串的路径找出来,而且有些字符串可能会出现在不同的路径上(当然,这些路径的大小必定都是一样的且最小)。这道题的方法与上一题不同的,这里采用unordered_multimap来存储树的每一条边(严格来说,应该是树,因为一个节点可能有多个父节点)。在搜索的过程中,如果一个满足变换条件的字符串第一次被搜索到,那么把这个字符串加入队列中,如果这个字符串之前被搜索过且当前搜索的深度与之前搜索到它的深度一样的话,那么将该字符串与其父节点的边存入unordered_multimap中,切忌不可在将该字符串再加入队列中(我之前的超时就是因为又把该字符串加入队列)。这里,构造解的过程也挺巧妙的,我也不知道怎么表达,看代码吧:

     1 class Solution {
     2 public:
     3     vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
     4         if(start == end){
     5             vector<vector<string> > result;
     6             result.push_back(vector<string>(1,start));
     7             return result;
     8         }
     9         int len = start.size();
    10         map<string,int> depth;
    11         unordered_multimap<string,string> tree;
    12         queue<string> Q;
    13         Q.push(start);
    14         tree.insert(pair<string,string>("",start));
    15         depth[start] = 1;
    16         while(!Q.empty()){
    17             string s = Q.front();
    18             if(s == end){
    19                 break;
    20             }
    21             for(int i = 0; i < len; ++i){
    22                 for(char c = 'a'; c <= 'z'; ++c){
    23                     if(s[i] != c){
    24                         string temp = s;
    25                         temp[i] = c;
    26                         if(dict.find(temp) != dict.end() ){
    27                             if(depth.find(temp) == depth.end()){
    28                                 Q.push(temp);
    29                                 tree.insert(pair<string,string>(s,temp));
    30                                 depth[temp] = depth[s] + 1;
    31                             }else if(depth[temp] == depth[s] + 1){
    32                                 tree.insert(pair<string,string>(s,temp));
    33                             }
    34                         }
    35                     }
    36                 }
    37                
    38             }
    39             Q.pop();
    40         }
    41         return getPath(tree,start,end);
    42     }
    43  
    44     void getPathCore(unordered_multimap<string,string> &tree, 
    45              string start, string end, 
    46              vector<string> &path, vector<vector<string>> &paths)
    47 
    48 {
    49     if(start == end) {
    50         path.push_back(start);
    51         paths.push_back(path);
    52         path.pop_back();
    53     }
    54     else {
    55         path.push_back(start);
    56 
    57         pair<unordered_multimap<string,string>::iterator,unordered_multimap<string,string>::iterator> ret;
    58         unordered_multimap<string,string>::iterator it;
    59         ret = tree.equal_range(start);
    60         for(it = ret.first; it != ret.second; it++) {
    61             getPathCore(tree, it->second, end, path, paths);
    62         }
    63 
    64         path.pop_back();
    65     }
    66 }
    67 
    68 vector<vector<string>> getPath(unordered_multimap<string,string> &tree, string start, string end) 
    69 {
    70     vector<vector<string>> paths;
    71     vector<string> path;
    72 
    73     if(tree.find(start) != tree.end())
    74         getPathCore(tree, start, end, path, paths);
    75 
    76     return paths;
    77 }
    78 };
  • 相关阅读:
    #背包#nssl 1488 上升子序列
    #环#nssl 1487 图
    #分治#JZOJ 4211 送你一颗圣诞树
    #概率,dp#JZOJ 4212 我想大声告诉你
    #并查集#JZOJ 4223 旅游
    #dp#nssl 1478 题
    #对顶堆#nssl 1477 赛
    #线段树,离散#nssl 1476 联
    #折半搜索,状压dp#nssl 1471 Y
    #并查集,线性筛#nssl 1470 X
  • 原文地址:https://www.cnblogs.com/boostable/p/leetcode_word_ladder.html
Copyright © 2020-2023  润新知