# leetcode 解题报告 Word Ladder II

340人阅读 评论(0)

Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

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

For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["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.

That heavily depends on the structure of the search tree and the number and location of solutions. If you know a solution is not far from the root of the tree, a breadth first search (BFS) might be better. If the tree is very deep and solutions are rare, depth first search (DFS) might take an extremely long time, but BFS could be faster. If the tree is very wide, a BFS might need too much memory, so it might be completely impractical. If solutions are frequent but located deep in the tree, BFS could be impractical. If the search tree is very deep you will need to restrict the search depth for depth first search (DFS), anyway (for example with iterative deepening).

--------------------------------------------------------------------------------------

BFS is going to use more memory depending on the branching factor... however, BFS is a complete algorithm... meaning if you are using it to search for something in the lowest depth possible, BFS will give you the optimal solution. BFS space complexity is O(b^d)... the branching factor raised to the depth (can be A LOT of memory).

DFS on the other hand, is much better about space however it may find a suboptimal solution. Meaning, if you are just searching for a path from one vertex to another, you may find the suboptimal solution (and stop there) before you find the real shortest path. DFS space complexity is O(|V|)... meaning that the most memory it can take up is the longest possible path.

They have the same time complexity.

void search(string &word, string &end, unordered_set<string> &dict, int level)
{
if(word == end)
return;

if( level == dict.size())
return;

for(int i = 0; i < word.length(); i++)
{
for(int ch = 'a'; j <='z'; j++)
{
string tmp = word;
if(tmp[i] == ch)
continue;
tmp[i] = ch;
if(dict.count(tmp) > 0)
search(tmp, end, dict, level+1);
}
}            

hot---> hop, tot, dot, pot, hog

dot--->dog

hog--->dog, cog

ok。至此，问题算是基本解决了，剩下的就是如何生成路径。其实很简单，对于这种“特殊”的图，我们可以直接DFS搜索，节点碰到目标单词就返回。

dog--->dot, hog

cog--->hog

hop--->hot

tot--->hot

dot--->hot

pot--->hot

hog--->hot

 1 class Solution {
2 public:
3 vector<string> temp_path;
4 vector<vector<string>> result_path;
5
6 void GeneratePath(unordered_map<string, unordered_set<string>> &path, const string &start, const string &end)
7 {
8     temp_path.push_back(start);
9     if(start == end)
10     {
11         vector<string> ret = temp_path;
12         reverse(ret.begin(),ret.end());
13         result_path.push_back(ret);
14         return;
15     }
16
17     for(auto it = path[start].begin(); it != path[start].end(); ++it)
18     {
19             GeneratePath(path, *it, end);
20             temp_path.pop_back();
21     }
22 }
23 vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict)
24 {
25     temp_path.clear();
26     result_path.clear();
27
28     unordered_set<string> current_step;
29     unordered_set<string> next_step;
30
31     unordered_map<string, unordered_set<string>> path;
32
33     unordered_set<string> unvisited = dict;
34
35     if(unvisited.count(start) > 0)
36         unvisited.erase(start);
37
38     current_step.insert(start);
39
40     while( current_step.count(end) == 0 && unvisited.size() > 0 )
41     {
42         for(auto pcur = current_step.begin(); pcur != current_step.end(); ++pcur)
43         {
44             string word = *pcur;
45
46             for(int i = 0; i < start.length(); ++i)
47             {
48                 for(int j = 0; j < 26; j++)
49                 {
50                     string tmp = word;
51                     if( tmp[i] == 'a' + j )
52                         continue;
53                     tmp[i] = 'a' + j;
54                     if( unvisited.count(tmp) > 0 )
55                     {
56                         next_step.insert(tmp);
57                         path[tmp].insert(word);
58                     }
59                 }
60             }
61         }
62
63         if(next_step.empty()) break;
64         for(auto it = next_step.begin() ; it != next_step.end(); ++it)
65         {
66             unvisited.erase(*it);
67         }
68
69         current_step = next_step;
70         next_step.clear();
71     }
72
73     if(current_step.count(end) > 0)
74         GeneratePath(path, end, start);
75
76     return result_path;
77 }
78 };
ps：
class Solution {
public:
vector<string> temp_path;
vector<vector<string>> result_path;
void  generatPath(unordered_map<string, unordered_set<string>> &path,string start,string end){
temp_path.push_back(start);
if(start==end){
vector<string> ret=temp_path;
reverse(ret.begin(),ret.end());
result_path.push_back(ret);
return;
}
for(unordered_set<string>::iterator it=path[start].begin();it!=path[start].end();it++){
generatPath(path,*it,end);
temp_path.pop_back();
}
}
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict)
{
temp_path.clear();
result_path.clear();

unordered_set<string> unvisited=dict;
unordered_set<string> currLevel;
unordered_set<string> nextLevel;
unordered_map<string, unordered_set<string>> path;//key string 是前驱，set是后继，从下往上走

if(unvisited.count(start)>0)
unvisited.erase(start);
currLevel.insert(start);
//生成从end到start（从下到上）的 path -- 图， 后继set<string> = path[前驱string]
//已经找到end了就退出，或者dict中单词都用完了还没找到
while(currLevel.count(end)==0 && unvisited.size() > 0){
for(unordered_set<string>::iterator it=currLevel.begin();it!=currLevel.end();it++){
string word=*it;
for(int i=0;i<word.size();i++){
for(char c='a';c<='z';c++){
if(c==word[i])
continue;
string tmp=word;
tmp[i]=c;
if(unvisited.count(tmp)>0){
nextLevel.insert(tmp);
path[tmp].insert(word);
}
}
}
}
for(unordered_set<string>::iterator it=nextLevel.begin();it!=nextLevel.end();it++){
unvisited.erase(*it);
}
currLevel=nextLevel;
if(currLevel.size()==0)
break;
nextLevel.clear();
}
//生成从start到end的路径result_path
if(currLevel.count(end)>0)
generatPath(path,end,start);
return result_path;
}
};

0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：150681次
• 积分：3142
• 等级：
• 排名：第12667名
• 原创：154篇
• 转载：115篇
• 译文：0篇
• 评论：3条
阅读排行
评论排行
最新评论