给出两个单词(start和end)和一个字典,找出所有从start到end的最短转换序列
比如:
- 每次只能改变一个字母。
- 变换过程中的中间单词必须在字典中出现。
样例
给出数据如下:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
返回
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
注意
- 所有单词具有相同的长度。
- 所有单词都只包含小写字母。
class Solution {
public:
/**
* @param start, a string
* @param end, a string
* @param dict, a set of string
* @return a list of lists of string
*/
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
// write your code here
vector<vector<string> > result;
set<string> cur;
cur.insert(start);
set<string> next;
map<string, set<string> > parents;
unordered_set<string> unused = dict;
unused.insert(end);
visit(cur, end, next, unused, parents);
if (parents.find(end) != parents.end())
{
vector<string> buf;
generatePath(start, end, parents, buf, result);
}
return result;
}
private:
void visit(set<string> &cur, string &end, set<string> &next,
unordered_set<string> &unused, map<string, set<string> > &parents)
{
while (parents.find(end) == parents.end() && !unused.empty())
{
next.clear();
for (set<string>::iterator it = cur.begin(); it != cur.end(); it++)
{
string word = *it;
string temp = *it;
for (int i = 0; i < (*it).length(); i++)
{
for (char a = 'a'; a <= 'z'; a++)
{
temp = *it;
if (a != word[i])
{
temp[i] = a;
if (unused.find(temp) != unused.end())
{
parents[temp].insert(word);
next.insert(temp);
}
}
}
}
}
if (next.empty())
{
return;
}
cur = next;
for (set<string>::iterator it = next.begin(); it != next.end(); it++)
{
unused.erase(*it);
}
}
}
void generatePath(string &start, string cur, map<string, set<string> > &parents,
vector<string> &buf, vector<vector<string> > &result)
{
buf.insert(buf.begin(), cur);
if (cur == start)
{
result.push_back(buf);
}
else
{
for (set<string>::iterator it = parents[cur].begin(); it != parents[cur].end(); it++)
{
generatePath(start, *it, parents, buf, result);
}
}
buf.erase(buf.begin());
}
};