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 };

 

你可能感兴趣的:(LeetCode)