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.
It is also a BFS algorithm. Since there is no weight on each path, Dijkstra is not necessary.
There are some subtle details should be handled.
1. store the current shortest path when we visit a node.
2. update the shortest path when visiting a node
3. push adjacent nodes in the queue
class Solution { public: vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) { //variable declaration queue<string> q; unordered_map<string, vector<vector<string>>> visitedPath; vector<vector<string>> re; vector<string> thisRe; //extreme cases if(start == end){ thisRe.push_back(start); re.push_back(thisRe); return re; } else if(isOneEditDistance(start, end)){ thisRe.push_back(start); thisRe.push_back(end); re.push_back(thisRe); return re; } else{ //ordinary cases q.push(start); thisRe.push_back(start); vector<vector<string>> paths; paths.push_back(thisRe); visitedPath[start] = paths; while(!q.empty()){ string word = q.front(); q.pop(); if(isOneEditDistance(word, end)){ if(visitedPath.find(end) != visitedPath.end()){ //end is visited before if(visitedPath[end][0].size() < visitedPath[word][0].size() + 1){ //previous path is shorter than current path break; } else{ for(auto it = visitedPath[word].begin(); it != visitedPath[word].end(); it++){ vector<string> tmpPath = *it; tmpPath.push_back(end); visitedPath[end].push_back(tmpPath); } } } else{ //end is not visited before visitedPath[end] = vector<vector<string>>(); for(auto it = visitedPath[word].begin(); it != visitedPath[word].end(); it++){ vector<string> tmpPath = *it; tmpPath.push_back(end); visitedPath[end].push_back(tmpPath); } } } //not the last step else{ for(size_t i = 0; i < word.size(); i++){ for(char c = 'a'; c <= 'z'; c++){ if(word[i] == c) continue; string tmps = word; tmps[i] = c; if(dict.find(tmps) != dict.end()){ //tmps exists in dict if(visitedPath.find(tmps) != visitedPath.end()){ //tmps exists in visitedPath if(visitedPath[tmps][0].size() < visitedPath[word][0].size() + 1){ //previous path to tmps is shorter than current path continue; } else{ //previous path and current path have same length for(auto it = visitedPath[word].begin(); it != visitedPath[word].end(); it++){ //vector<string>* it vector<string> path = *it; path.push_back(tmps); visitedPath[tmps].push_back(path); } } } else{ //tmps not exist in visitedPath q.push(tmps); visitedPath[tmps] = vector<vector<string>>(); for(auto it = visitedPath[word].begin(); it != visitedPath[word].end(); it++){ //vector<string>* it vector<string> path = *it; path.push_back(tmps); visitedPath[tmps].push_back(path); } } } else{ //tmp not exist in dict } } } } } return visitedPath.find(end) == visitedPath.end()?re:visitedPath[end]; } } bool isOneEditDistance(string a, string b){ int diff = 0; for(size_t i = 0; i < a.size(); i++){ if(a[i] == b[i]){ continue; } else{ diff++; } } return diff == 1? true: false; } };