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:
- 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"]
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:
- 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.
地址: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 };