• LeetCode | Word Ladder II


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

    Only one letter can be changed at a time
    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.

     从Word Ladder 这道题我们大概知道怎么做了。先用BFS遍历到end,顺便记录下每个节点的前置节点。最后用dfs把整条路径给输出来。

    Word Ladder 中有两种方法,用方法一保存前置节点不知道为什么总会Memory Limit Exceeds.

    后来仔细一想,其实和Word Ladder 中提到的bug一样,同层的点可能也是邻居(只差一个字符),那么一个点就会重复地被加入到queue里面,导致了pres数组增大。

    用第二种方法就AC了。

     1 class Solution {
     2 public:
     3     int ladderLength(string start, string end, unordered_set<string> &dict) {
     4         if (dict.empty()) return 0;
     5         if (start.empty() || end.empty()) return 0;
     6         if (start.length() != end.length()) return 0;
     7         dict.insert(end);
     8         
     9         vector<unordered_set<string> > layers(2);
    10         int cur = 0, pre = 1;
    11         layers[pre].insert(start);
    12         dict.erase(start);
    13         
    14         int n = start.length();
    15         
    16         int h = 1;
    17         bool found = false;
    18         while (!layers[pre].empty()) {
    19             for (unordered_set<string>::iterator it = layers[pre].begin(); it != layers[pre].end(); ++it) {
    20                 dict.erase(*it);
    21             }
    22             layers[cur].clear();           
    23             for (unordered_set<string>::iterator it = layers[pre].begin(); it != layers[pre].end(); ++it) {
    24                 for (int i = 0; i < n; ++i) {
    25                     string next(*it);
    26                     for (char c = 'a'; c <= 'z'; ++c) {
    27                         if ((*it)[i] == c) continue;
    28                         next[i] = c;
    29                         
    30                         if (dict.count(next) > 0) {
    31                             if (next == end) found = true;
    32                             pres[next].push_back(*it);
    33                             
    34                             layers[cur].insert(next);
    35                         }
    36                     }
    37                 }
    38             }
    39             
    40             cur = !cur;
    41             pre = !pre;
    42             h++;
    43             if (found) return h;
    44         }
    45         
    46         return 0;
    47     }
    48     
    49     vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
    50         int min = ladderLength(start, end, dict);
    51         if (min == 0) return rets;
    52         
    53         vector<string> ret;
    54         build(start, end, ret);
    55         return rets;
    56     }
    57     
    58     void build(string &start, string end, vector<string> &ret) {
    59         if (end == start) {
    60             ret.insert(ret.begin(), start);
    61             rets.push_back(ret);
    62             ret.erase(ret.begin());
    63             return;
    64         }
    65         
    66         ret.insert(ret.begin(), end);
    67         for (vector<string>::iterator it = pres[end].begin(); it != pres[end].end(); ++it) {
    68             build(start, *it, ret);
    69         }
    70         ret.erase(ret.begin());
    71     }
    72     
    73 private:
    74     unordered_map<string, vector<string> > pres;
    75     vector<vector<string> > rets;
    76 };

     第三次刷,用了一个map使得每一层的string都惟一,去重。还有在build的时候,先反序地生成,最终再reverse过来,因为vector的头部插入的开销还是蛮大的。

    AC, 664ms,相当快了。

     1 class Solution {
     2 public:
     3     bool findPath(string start, string end, unordered_set<string> &dict, unordered_map<string, vector<string> > &prev) {
     4         vector<vector<string> > layers(2);
     5         int cur = 0, next = 1, n = 1;
     6         layers[cur].push_back(start);
     7         dict.insert(end);
     8         
     9         bool flag = false;
    10         while (!layers[cur].empty()) {
    11             layers[next].clear();
    12             for (auto str: layers[cur]) {
    13                 dict.erase(str);
    14             }
    15             unordered_map<string, bool> contained;
    16             
    17             for (auto str: layers[cur]) {
    18                 if (str == end) break;
    19                 for (int i = 0; i < str.length(); i++) {
    20                     string tmp(str);
    21                     for (char c = 'a'; c <= 'z'; c++) {
    22                         if (str[i] == c) continue;
    23                         tmp[i] = c;
    24                         if (dict.count(tmp) > 0) {
    25                             if (tmp == end) {
    26                                 flag = true;   
    27                             }
    28                             if (contained.count(tmp) == 0) layers[next].push_back(tmp);
    29                             contained[tmp] = true;
    30                             prev[tmp].push_back(str);
    31                         }
    32                     }
    33                 }
    34             }
    35             if (flag) break;
    36             cur = !cur; next = !next;
    37         }
    38         
    39         return flag;
    40     }
    41     
    42     void build(string start, string end, vector<vector<string> > &ans, 
    43                 unordered_map<string, vector<string> > &prev, vector<string> &ret) {
    44             ret.push_back(end);
    45             if (end == start) {
    46                 ans.push_back(ret);
    47             } else {
    48                 for (auto str: prev[end]) {
    49                     build(start, str, ans, prev, ret);
    50                 }
    51             }
    52             ret.pop_back();
    53     }
    54     
    55     void reverse(vector<string> &path) {
    56         for (int i = 0, j = path.size() - 1; i < j; i++, j--) swap(path[i], path[j]);    
    57     }
    58     
    59     vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
    60         vector<vector<string> > ans;
    61         unordered_map<string, vector<string> > prev;
    62         
    63         if (!findPath(start, end, dict, prev)) return ans;
    64         
    65         vector<string> ret;
    66         build(start, end, ans, prev, ret);
    67         
    68         for (auto it = ans.begin(); it != ans.end(); it++) {
    69             reverse(*it);
    70         }
    71         return ans;
    72     }
    73 };
  • 相关阅读:
    POJ 2135 Farm Tour(最小费用最大流,变形)
    HDU 1503 Advanced Fruits (LCS,变形)
    HDU Senior's Gun (水题)
    POJ 3648 Wedding (2-SAT,经典)
    HDU 3549 Flow Problem 流问题(最大流,入门)
    解决在eclipse中导入项目名称已存在的有关问题
    如何将js导入时的小红叉去掉
    servlet传值到servlet传值问题
    转发重定向的用法
    parameter与attribute的使用场合(转载自草原和大树)
  • 原文地址:https://www.cnblogs.com/linyx/p/3656196.html
Copyright © 2020-2023  润新知