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 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.
分析:
本题的大体思路与Word Ladder相似,不同之处在于这道题需要输出所有满足条件的路径,因此需要做以下几点改动:
1. 首先需要保存当前节点向其前一节点的映射关系,采用unordered_map,由于可能有多个父节点,因此val的类型是一个容器;
2. 为了输出路径,需要添加一个生成路径的函数,采用回溯法,生成的路径是由终点至起点的,因此需要reverse;
3. 退出的条件不同,在Word Ladder中只要找到一次就可以直接退出,而本题中在找到之后仍然需要将当前层的所有节点遍历完,否则会漏掉长度相同的其他路径。
代码:
class Solution {
public:
void gen_path(unordered_map<string,vector<string>> &father,vector<vector<string>> &res,vector<string> path,string beg,string endd)
{
path.push_back(endd);
if(endd==beg)
{
reverse(path.begin(),path.end());
res.push_back(path);
return;
}
for(int i=0;i<father[endd].size();++i)
gen_path(father,res,path,beg,father[endd][i]);
}
vector<vector<string>> findLadders(string beginWord, string endWord, unordered_set<string> &wordList) {
unordered_set<string> cur,next;
unordered_set<string> vis;
unordered_map<string,vector<string>> father;
wordList.insert(endWord);
auto extend = [&](string s)
{
unordered_set<string> res;
for(int i=0;i<s.size();++i)
{
for(char c='a';c<='z';++c)
{
if(c==s[i]) continue;
swap(c,s[i]);
if(wordList.count(s)>0&&vis.count(s)==0)
res.insert(s);
swap(c,s[i]);
}
}
return res;
};
bool found = 0;
cur.insert(beginWord);
while(!cur.empty()&&!found)
{
for(auto &word:cur)
vis.insert(word);
for(auto &word:cur)
{
auto states = extend(word);
for(auto &state:states)
{
if(state==endWord) found = 1;
next.insert(state);
father[state].push_back(word);
}
}
cur.clear();
swap(cur,next);
}
vector<vector<string>> res;
if(found)
{
vector<string> path;
gen_path(father,res,path,beginWord,endWord);
}
return res;
}
};