您的位置:首页 > 其它

[Leetcode 126] Word Ladder II

2017-07-05 11:17 429 查看
Question

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

Only one letter can be changed at a time

Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
Return
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]


思路

这个题是一个无向图查找所有的最短路径的题。

我首先是想到了用深度搜索(DFS)去做。但是写出的代码只能通过 wordList 比较小的情况,wordList大的时候总是报 Time Limit Exceed错误。我在vs上调试时 发现原因是 递归调用层次太深,程序就死了。

后面我采用空间换时间策略, 用BFS算法重写, 通过了。

另外有一种思路是 BFS+DFS. 即先用BFS 把无向图变成有向图, 把每个节点的父节点和子节点保存下来,再用DFS 去查找最短路径,有兴趣的可以在网上找一下

-代码如下:

class Solution {
public:
/* compare() 是比较string a 和 b 有几个字母不同 */
bool compare(string &a, string &b) {
int cnt = 0;
if (a.size() == b.size())
for (int i = 0; i < a.size(); ++i) {
if (a[i] != b[i]) {
++cnt;
if (cnt > 1) break;
}
}
return cnt == 1;
}
/*
build() 找出节点 word 的所有相邻节点,(即找出与 word 只有一个字符不同的所有 string), 保存到   set<string> 中
*/
set<string> build(string word, vector<string> &wordList) {
set<string> ret;
for (auto a : wordList) {
if (compare(a, word)) {
ret.insert(a);
}
}
return ret;
}

vector<vector<string>> findLadders(string beginWord, string endWord, vector<string> wordList) {
vector<vector<string>> ret;  // 返回
if ((find(wordList.begin(), wordList.end(), endWord)) == wordList.end()) return ret;
map<string, set<string>> str_set;
queue<string> s;
//记录从初始节点beginWord到当前节点的最短路径的长度
map<string, int> flash;
//记录从初始节点beginWord到当前节点的所有最短路径的,这些路径保存到set<vector<string>>中
map<string, set<vector<string>>> route;
//建立无向图,保存到 str_set 中
for (auto a : wordList) {
str_set[a] = build(a, wordList);
flash[a] = 0;
}
//将beginWord加入到图中,如果beginWord本身在图中也不会有影响
str_set[beginWord] = build(beginWord, wordList);
flash[beginWord] = 1;  //beginWord 到beginWord 路径长度为1,相应路径保存到route[beginWord]中
route[beginWord].insert({ beginWord });
s.push(beginWord);
while (!s.empty()) {
string val = s.front();
for (auto &a : str_set[val]) {
//遍历val的所有邻接点, flash[a] == 0 表示该节点该节点 第一次被访问,
//flash[a] >= (flash[val] + 1) 表示发现比当前找到的路径的长度相等或者更短的新路径,要更新
if (flash[a] == 0 || flash[a] >= (flash[val] + 1)) {

//找到更短的路径,则把先前保存的路径清除
if (flash[a] > flash[val] + 1){
route[a].clear();
flash[a] = flash[val] + 1;
}
int temp = 1;
for (auto b : route[val]) {
b.push_back(a);
//如果该路径已经保存在已有路径中,是重复访问,跳出,temp置0
if (route[a].find(b) != route[a].end())
{
temp = 0;
break;
}
route[a].insert(b);
}
//更新后的节点要重新加入到 队列中
if (temp)
s.push(a);
}
if (a == endWord) break;
}
s.pop();
}
for (auto a : route[endWord])
ret.push_back(a);
return ret;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: