題目:
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:
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:
解題思路:
#include <iostream> #include <string> #include <vector> #include <queue> #include <unordered_set> #include <unordered_map> #include <algorithm> using namespace std; /** 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. */ class Solution { public: vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) { vector<vector<string>> resvec; if(start.empty() || end.empty() || dict.empty()) return resvec; unordered_map<string, vector<string>> premap; //這裡需要用到兩個vector來模擬兩個佇列而不是直接用兩個佇列,是因為需要對佇列進行遍歷,queue做不到 vector<string> squ[2]; squ[0].push_back(start); bool qid = false; bool finish = false; while(!squ[qid].empty()) { squ[!qid].clear(); vector<string>::iterator iter; for(iter = squ[qid].begin(); iter != squ[qid].end(); ++iter) dict.erase(*iter);//從dict中刪除同一層的所有節點,以免造成迴圈操作 for(iter = squ[qid].begin(); iter != squ[qid].end(); ++iter)//處理同一層節點 { string curstr = *iter; for(int i = 0; i < curstr.size(); i++) { char t = curstr[i]; for(char j = 'a'; j <= 'z'; j++) { if(j == curstr[i]) continue; curstr[i] = j; if(curstr == end) { finish = true; premap[curstr].push_back(*iter); } else if(dict.count(curstr) > 0) { squ[!qid].push_back(curstr); premap[curstr].push_back(*iter); } } curstr[i] = t; } } if(finish)//說明已經處理到了end節點,可以直接break迴圈,進行結果重構了 break; qid = !qid;//表示將要處理的下一層 } if(premap.count(end) == 0)//表明end節點的父節點不存在,所有沒有到end的轉換,直接返回空resvec return resvec; vector<string> tmp; getResult(resvec, tmp, premap, start, end); return resvec; } //DFS void getResult(vector<vector<string> > &resvec, vector<string> &tmp, unordered_map<string, vector<string> > &premap, string &start, string &cur) { tmp.push_back(cur); if (cur == start) { resvec.push_back(tmp); reverse(resvec.back().begin(), resvec.back().end()); } else { vector<string> v = premap[cur]; for (int i = 0; i < v.size(); i++) { getResult(resvec, tmp, premap, start, v[i]); } } tmp.pop_back(); } }; int main(void) { string start("hit"); string end("cog"); string strarr[] = {"hot","dot","dog","lot","log"}; int n = sizeof(strarr) / sizeof(strarr[0]); unordered_set<string> dict(strarr, strarr+n); Solution solution; vector<vector<string>> resvec = solution.findLadders(start, end, dict); vector<vector<string>>::iterator iter; for(iter = resvec.begin(); iter != resvec.end(); ++iter) { vector<string> tmp = *iter; vector<string>::iterator it; for(it = tmp.begin(); it != tmp.end(); ++it) cout<<*it<<" "; cout<<endl; } return 0; }
以下附網上大神AC程式碼一份:
class Solution { public: vector<vector<string> > findLadders(string start, string end, unordered_set<string> &dict) { result_.clear(); unordered_map<string, vector<string>> prevMap; for(auto iter = dict.begin(); iter != dict.end(); ++iter) prevMap[*iter] = vector<string>(); vector<unordered_set<string>> candidates(2); int current = 0; int previous = 1; candidates[current].insert(start); while(true) { current = !current; previous = !previous; for (auto iter = candidates[previous].begin(); iter != candidates[previous].end(); ++iter) dict.erase(*iter); candidates[current].clear(); for(auto iter = candidates[previous].begin(); iter != candidates[previous].end(); ++iter) { for(size_t pos = 0; pos < iter->size(); ++pos) { string word = *iter; for(int i = 'a'; i <= 'z'; ++i) { if(word[pos] == i)continue; word[pos] = i; if(dict.count(word) > 0) { prevMap[word].push_back(*iter); candidates[current].insert(word); } } } } if (candidates[current].size() == 0) return result_; if (candidates[current].count(end)) break; } vector<string> path; GeneratePath(prevMap, path, end); return result_; } private: void GeneratePath(unordered_map<string, vector<string>> &prevMap, vector<string>& path, const string& word) { if (prevMap[word].size() == 0) { path.push_back(word); vector<string> curPath = path; reverse(curPath.begin(), curPath.end()); result_.push_back(curPath); path.pop_back(); return; } path.push_back(word); for (auto iter = prevMap[word].begin(); iter != prevMap[word].end(); ++iter) GeneratePath(prevMap, path, *iter); path.pop_back(); } vector<vector<string>> result_; };