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.
从AC率来看,貌似是最难的一个题,不过可以在Word Ladder I的基础上改进。求路径,典型的需要记录前驱单词,这个可以用map来实现。不过一个单词可能有多个前驱,所以需要用一个vector来保存所有的前驱。因为求最短路径,需要把最小深度记录下来,如果当前深度大于最小深度,说明不是有效前驱,跳过。找到目标单词之后,可以根据前驱单词列表递归构建所有的最短路径。
思路到了,感觉也不是很复杂。
class Solution {
public:
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
bool found = false;
int step = 1;
queue<string> cur_trans, next_trans;
cur_trans.push(start);
while (!cur_trans.empty()) {
string cur = cur_trans.front();
cur_trans.pop();
if (cur == end) {
found = true;
break;
}
else {
getTransforms(cur, step+1, dict, next_trans);
}
if (cur_trans.empty()) {
cur_trans.swap(next_trans);
++step;
}
}
if (found) {
vector<string> path;
path.push_back(end);
fillLadders(start, path);
}
return result;
}
void fillLadders(const string &start, vector<string> &path) {
if (!path.empty() && path.back() == start) {
vector<string> ladder;
for (int i = path.size() - 1; i >= 0; --i) {
ladder.push_back(path[i]);
}
result.push_back(ladder);
return;
}
auto next = visited.find(path.back());
for (int i = 0; i < next->second.second.size(); ++i) {
path.push_back(next->second.second[i]);
fillLadders(start, path);
path.pop_back();
}
}
void getTransforms(string orig, int step, unordered_set<string> &dict, queue<string>& transforms) {
string next = orig;
for (int i = 0; i < next.size(); ++i) {
char tmp = next[i];
for (char j = 'a'; j <= 'z'; ++j) {
if (j != tmp) {
next[i] = j;
if (dict.find(next) != dict.end()) {
auto ladder = visited.find(next);
if (ladder == visited.end()) {
transforms.push(next);
vector<string> source;
source.push_back(orig);
visited[next] = make_pair(step, source);
}
else if (step <= ladder->second.first) {
ladder->second.second.push_back(orig);
}
}
}
}
next[i] = tmp;
}
}
private:
vector<vector<string>> result;
unordered_map<string, pair<int, vector<string>>> visited;
};