[LeetCode] word ladder II
http://www.lintcode.com/zh-cn/problem/word-ladder-ii/#
给出两个单词(start和end)和一个字典,找出所有从start到end的最短转换序列
比如:
- 每次只能改变一个字母。
- 变换过程中的中间单词必须在字典中出现。
样例
给出数据如下:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
返回
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
注意
- 所有单词具有相同的长度。
- 所有单词都只包含小写字母。
// Solution // // 1) Using BSF algorithm build a graph like below // 2) Using DSF to parse the tree to the transformation path. // // For example: // // start = "hit" // end = "cog" // dict = ["hot","dot","dog","lot","log","dit","hig", "dig"] // // +-----+ // +-------------+ hit +--------------+ // | +--+--+ | // | | | // +--v--+ +--v--+ +--v--+ // | dit | +-----+ hot +---+ | hig | // +--+--+ | +-----+ | +--+--+ // | | | | // | +--v--+ +--v--+ +--v--+ // +----> dot | | lot | | dig | // +--+--+ +--+--+ +--+--+ // | | | // +--v--+ +--v--+ | // +----> dog | | log | | // | +--+--+ +--+--+ | // | | | | // | | +--v--+ | | // | +--->| cog |<-- + | // | +-----+ | // | | // | | // +----------------------------------+ class Solution { public: vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) { unordered_map<string, unordered_set<string>> parent = BFS(start, end, dict); vector<string> path; path.push_back(start); vector<vector<string>> paths; DFS(start, end, parent, path, paths); return paths; } private: unordered_map<string, unordered_set<string>> BFS(const string &start, const string &end, const unordered_set<string> &dict) { /* 用于存储BFS形成的图结构 */ unordered_map<string, unordered_set<string>> parent; /* 模拟图结构的每一层 */ unordered_set<string> level[3]; unordered_set<string> *previousLevel = &level[0]; unordered_set<string> *currentLevel = &level[1]; unordered_set<string> *nextLevel = &level[2]; unordered_set<string> *p = NULL; // 用于交换指针用 currentLevel->insert(start); /* BFS */ bool flag = false; // 当下一层插入的word中包含end,即退出BFS,因为所求为最短路径 while (flag == false) { // 还未到最后一层 // 用于存储下一层的newWord(如果存在) nextLevel->clear(); // 处理当前层 for (const auto &word : *currentLevel) { // 当前层中的每一个word for (int ix = 0; ix < word.size(); ix++) { // 当前单词的每一个letter string newWord = word; for (char c = 'a'; c <= 'z'; c++) { // 对当前letter依次进行26个字母的替换 newWord[ix] = c; // 不在词典中或者之前层已经出现过 if (dict.count(newWord) == 0 || previousLevel->count(newWord) == 1 || currentLevel->count(newWord) == 1) { continue; } if (newWord == end) { flag = true; parent[word].insert(newWord); continue; } parent[word].insert(newWord); nextLevel->insert(newWord); } } } if (nextLevel->empty()) { break; } p = currentLevel; currentLevel = nextLevel; nextLevel = previousLevel; previousLevel = p; } if (flag == false) { parent.clear(); } return parent; } void DFS(const string &start, const string &end, unordered_map<string, unordered_set<string>> &parent, vector<string> &path, vector<vector<string>> &paths) { if (parent.find(start) == parent.end()) { if (start == end) { paths.push_back(path); } return; } for (const auto &word : parent[start]) { path.push_back(word); DFS(word, end, parent, path, paths); path.pop_back(); } } };