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 };
原文地址:https://www.cnblogs.com/linyx/p/3656196.html