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.
尝试过用queue来保存当前队列,用vector来保存那些扩展到的字符串,可惜TLE。
class Solution { public: vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) { if (start == end) { vector<string> v = {start}; ret.push_back(v); return ret; } if (dict.empty()) return ret; //Use vector to implement bfs operation queue<string> q; unordered_map<string, vector<string>> preStrMap; q.push(start); dict.erase(start); int currLevelLens = 1, nextLevelLens, head(0); string headStr, str; bool found = false; while (currLevelLens) { nextLevelLens = 0; vector<string> levelStrs; while (currLevelLens--) { // Traverse the node of current level headStr = q.front(); q.pop(); for (int i=0; i<headStr.size(); ++i) { for (char j='a'; j<='z'; ++j) { // transform if (headStr[i]==j) continue; str = headStr; str[i] = j; if (str == end) { // record the previous string found = true; preStrMap[end].push_back(headStr); continue; } if (dict.find(str) != dict.end()) { ++nextLevelLens; q.push(str); levelStrs.push_back(str); // record the string of next level preStrMap[str].push_back(headStr); // record the previous string } } } } if (found) break; for (int i=0; i<levelStrs.size(); ++i) dict.erase(levelStrs[i]); currLevelLens = nextLevelLens; if (!currLevelLens) return ret; } vector<string> paths; genPaths(paths, preStrMap, end); return ret; } private: void genPaths(vector<string>& paths, unordered_map<string,vector<string>> &preStrMap, string& curr) { paths.push_back(curr); if (preStrMap[curr].empty()) ret.push_back(vector<string>(paths.rbegin(), paths.rend())); for (auto itr = preStrMap[curr].begin(); itr != preStrMap[curr].end(); ++itr) { genPaths(paths, preStrMap, *itr); } paths.pop_back(); } vector<vector<string>> ret; };
然后用了两个unordered_set容器来保存,轻松通过。
class Solution { public: vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) { if (dict.empty()) return ret; //Use unordered_set to implement bfs operation unordered_set<string> q1, q2; unordered_map<string, vector<string>> preStrMap; q1.insert(start); dict.erase(start); while (true) { for (USS_CITR itr=q1.begin(); itr!=q1.end(); ++itr) { string str = *itr; for (int i=0; i<str.size(); ++i) { for (int j='a'; j<='z'; ++j) { if (str[i] == j) { continue; } char c = str[i]; str[i] = j; if (dict.find(str) != dict.end() || str==end) { q2.insert(str); preStrMap[str].push_back(*itr); } str[i] = c; } } } if (q2.find(end) != q2.end()) { break; } for (USS_CITR itr=q2.begin(); itr!=q2.end(); ++itr) { dict.erase(*itr); } q1.clear(); q1.swap(q2); if (q1.empty()) { return ret; } } vector<string> paths; genPaths(paths, preStrMap, end); return ret; } private: typedef unordered_set<string>::const_iterator USS_CITR; void genPaths(vector<string>& paths, unordered_map<string,vector<string>> &preStrMap, string& curr) { paths.push_back(curr); if (preStrMap[curr].empty()) ret.push_back(vector<string>(paths.rbegin(), paths.rend())); for (auto itr = preStrMap[curr].begin(); itr != preStrMap[curr].end(); ++itr) { genPaths(paths, preStrMap, *itr); } paths.pop_back(); } vector<vector<string>> ret; };