Question
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.
Thoughts
1. preprocess the dictionary and build a graph. Adjacent nodes' distance is 1
2. using BFS iterator the graph
3. array father can record the father-son relation in iteration effectively
4. source code contains unordered_set, so when compiled under Linux system, extra flag must be used.
-std=c++11 or
-std=c++0x
code Runtime error. Can't figure out why...
#include <iostream> #include <string> #include <deque> #include <vector> #include <unordered_set> #include <unordered_map> #include <algorithm> using namespace std; class Solution { public: vector<string> dct; vector<int> graph[10010]; int father[10010]; int minDepth; vector<vector<string> > res; vector<string> party; vector<vector<string> > findLadders(string start, string end, unordered_set<string> &dict) { res.clear(), party.clear(); dct.clear(); for(int i = 0; i < dict.size()+3; i ++) { graph[i].clear(); father[i] = -3; minDepth = -1; } if(dist(start, end) == 1) { party.push_back(start), party.push_back(end); res.push_back(party); return res; } preprocess(dict); deque<int> queue; queue.clear(); for(int i = 0; i < dct.size(); i ++) { if(dist(start, dct[i]) == 1) { queue.push_back(i); father[i] = -1; //cout << i << endl; } } while(!queue.empty()) { int nextInt = queue.front(); queue.pop_front(); if(dist(end, dct[nextInt]) == 1) { // µÖ´ïÖÕµã, ´æ´¢Í˳ö // handler otherwise minDepth = assemble(party, nextInt, start, end); res.push_back(party); party.clear(); while(!queue.empty()) { int finalInt = queue.front(); queue.pop_front(); if(dist(end, dct[nextInt]) == 1) { if(assemble(party, finalInt, start, end) == minDepth) { res.push_back(party); party.clear(); }else{ return res; } } } return res; } for(int j = 0; j < graph[nextInt].size(); j ++) { int candidate = graph[nextInt][j]; if(father[candidate] == -3) { father[candidate] = nextInt; queue.push_back(candidate); } } } } int dist(const string &in, const string &ths) { int dis = 0; for(int i = 0; i < in.size() && dis < 2; i++) { if(in[i] != ths[i]) dis ++; } return dis; } void preprocess(unordered_set<string> &dict) { for(unordered_set<string>::iterator it1 = dict.begin(); it1 != dict.end(); it1 ++) dct.push_back(*it1); // ¹¹½¨ÁÚ½Ó±í for(int i = 0; i < dct.size(); i ++) { for(int j = 0; j < dct.size(); j ++) { if(dist(dct[i], dct[j]) == 1) { graph[i].push_back(j); } } } } int assemble(vector<string> &party, const int &nextInt, const string &start, const string &end) { party.push_back(end); int pre = nextInt; while(pre != -1 && pre >= 0) { //WA? party.push_back(dct[pre]); pre = father[pre]; } party.push_back(start); reverse(party.begin(), party.end()); return party.size(); } }; int main() { string start = "hot"; string end = "dog"; unordered_set<string> dict; dict.insert("hot"); dict.insert("dog"); dict.insert("dot"); //dict.insert("lot"); //dict.insert("log"); Solution solution; vector<vector<string> > res = solution.findLadders(start, end, dict); for(int i = 0; i < res.size(); i ++) { for(int j = 0; j < res[i].size(); j ++) { cout << res[i][j] << " "; } cout << endl; } return 0; }