题目:
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
给定两个单词(start 和 and ),以及一个字典,找出从 start 到 end 最短变换序列的长度。
1、一次只能改变一个字母。
2、每个中间词必须在字典中存在。
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.
思路:
先参考这个:http://blog.csdn.net/u012243115/article/details/41645063 。本题需要求出找到的所有路径,而链接的那一题只需要求出路径长度即可。
参考:http://www.tuicool.com/articles/eaQNNr 。
本题可以通过上一题的思路构造一个邻接表表示的图,对于题目给出的例子,可以构造如下图(图与题目给的数据有出入,大家明白那个意思就行了),图的数据结构我们可以用unorder_map<string,unordered_set<string>> graph 来表示:
然后用DFS遍历图,即可构造出路径。但是这样的图遍历会遍历到很多无用的路径,比如hot->hop ,或者 hot->pop 等,于是我们可以想到从下到上遍历,即从end找start,这样一定可以找到要求的正确路径,不需要遍历那些无用的路径。这样我们可以在用BFS构造图的时候构造一个反向邻接表,这样方便遍历。如下所示:
dog--->dot, hog
cog--->hog
hop--->hot
tot--->hot
dot--->hot
pot--->hot
hog--->hot
代码:
class Solution {
public:
vector<string> tmpPath;//用于构造当前路径
vector<vector<string> > result;//保存结果,即所有的路径
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict)
{
unordered_set<string> curLevel;//当前层次单词集合,也可以用vector<string>来表示,但是这个查找时候要用find函数
unordered_set<string> nextLevel;//下一层单词集合
unordered_set<string> unvisited(dict);//还未访问的结点
unordered_map<string,unordered_set<string> > graph;//图,反向邻接表
if(unvisited.count(start) != 0) //先清空unvisited中的start
unvisited.erase(start);
curLevel.insert(start);//第一层就一个单词start
//循环结束条件是找到end或者所有单词都遍历完了
while(curLevel.count(end) == 0 && unvisited.size() > 0)
{
//遍历当前层次的单词,找到下一层的单词,并构造图
for(auto iter = curLevel.begin() ; iter != curLevel.end() ; iter++)
{
string curWord = *iter;//当前层次的单词
for(int i = 0 ; i < start.size() ;i++)
{
for(char c = 'a' ; c < 'z' ; c++)
{
string tmp = curWord;
if(tmp[i] == c)
continue;
tmp[i] = c;
//如果找到,则插入下一层中,并且在图中构造tmp->word
if(unvisited.count(tmp) > 0)
{
nextLevel.insert(tmp);
graph[tmp].insert(curWord);//反向构造图,即下一层的单词指向上一层
}
}
}
}
if(nextLevel.empty())
break;
//当前层次遍历完,把下一层的单词从unvisited中删除
for(auto iter = nextLevel.begin() ; iter != nextLevel.end() ; iter++)
{
unvisited.erase(*iter);
}
curLevel = nextLevel;
nextLevel.clear();
}
//如果当前层次上存在end,说明找到了路径,则用DFS从下向上构造路径
if(curLevel.count(end) > 0)
DFS_GenPath(graph,end,start);
return result;
}
void DFS_GenPath(unordered_map<string,unordered_set<string> > &graph , string start , string end)
{
tmpPath.push_back(start);
if(start == end)
{
vector<string> tmp = tmpPath;
reverse(tmp.begin() , tmp.end());
result.push_back(tmp);
return;
}
for(auto iter = graph[start].begin() ; iter != graph[start].end() ; iter++)
{
DFS_GenPath(graph,*iter,end);
tmpPath.pop_back();
}
}
};