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
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.
与Word Ladder题目类似,但需要记录每条从start到end的路径。路径的记录方式,标记每个word的father word。注意本题要求的是所有的shortest path,即结果中的每条path的长度相同,每个word可以有多个father,但必须都来自同一层。
使用两个unordered_set用作ping-pong队列,逐层访问。
用visited标记已访问过的word时需要注意,不能立即将得到的新词添加到visited中,因为从上一层中别的word还有可能到达该词,而这些路径必须都保存。因此,在扩展新的层次之前,将上一层的所有节点标记为visited。
当找到end时,没必要再进行下一次层次的遍历,但该层次的所有word必须遍历完成。
恢复路径的时候,从end节点开始,利用保存的father信息进行DFS遍历,找到所有的路径并保存。
代码如下:
class Solution {
public:
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
unordered_set<string> visited;
unordered_set<string> queue1, queue2;
unordered_map<string, vector<string> > f;
bool flag = false;
queue1.insert(start);
while(!queue1.empty() && !flag)
{
for(auto str: queue1)
{
visited.insert(str);
}
for(auto str: queue1)
{
for(int i=0; i<str.size(); i++)
{
string old = str;
for(char c = 'a'; c <= 'z'; c++)
{
if(c == str[i]) continue;
swap(str[i], c);
if((dict.find(str) != dict.end() || str == end)
&& visited.find(str) == visited.end())
{
queue2.insert(str);
f[str].push_back(old);
}
if(str == end) flag = true;
swap(str[i], c);
}
}
}
queue1.clear();
swap(queue1, queue2);
}
vector<string> path;
vector<vector<string> > result;
if(flag)
{
path.push_back(end);
dfs(f, path, result, start);
}
return result;
}
void dfs(unordered_map<string, vector<string> > &f, vector<string> &path, vector<vector<string> > &result, string start)
{
if(path.back() == start)
{
result.push_back(path);
std::reverse(result.back().begin(), result.back().end());
return;
}
string cur = path.back();
vector<string> &fathers = f[cur];
for(int i=0; i<fathers.size(); i++)
{
path.push_back(fathers[i]);
dfs(f, path, result, start);
path.pop_back();
}
}
};