Word Ladder
Word Ladder
Given two words (beginWord and endWord), and a dictionary’s word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
Only one letter can be changed at a time.
Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
Note:
-
Return 0 if there is no such transformation sequence.
-
All words have the same length.
-
All words contain only lowercase alphabetic characters.
-
You may assume no duplicates in the word list.
-
You may assume beginWord and endWord are non-empty and are not the same.
Example 1:Input:
beginWord = “hit”,
endWord = “cog”,
wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]Output: 5
Explanation: As one shortest transformation is “hit” -> “hot” -> “dot” -> “dog” -> “cog”,
return its length 5.
Example 2:
Input:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,“dot”,“dog”,“lot”,“log”]
Output: 0
Explanation: The endWord “cog” is not in wordList, therefore no possible transformation.
解答:BFS搜索
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
if(wordList.empty()) return 0;
unordered_set<string> us(wordList.begin(), wordList.end());
if(us.find(endWord) == us.end()) return 0;
queue<pair<string, int> > q;
q.push(make_pair(beginWord, 1));
us.erase(beginWord);
string word;
while(!q.empty()){
auto p = q.front();
q.pop();
for(int i = 0; i < p.first.size(); ++i){
for(char c = 'a'; c <= 'z'; ++c){
word = p.first;
if(word[i] == c) continue;
word[i] = c;
if(word == endWord) return p.second+1;
if(us.find(word) != us.end()){
us.erase(word);
q.push(make_pair(word, p.second+1));
}
}
}
} return 0;
}
};
Word Ladder II
Word Ladder II
Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:
- Only one letter can be changed at a time
- Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
Note:
- Return an empty list if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
- You may assume no duplicates in the word list.
- You may assume beginWord and endWord are non-empty and are not the same.
Example 1:
Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
Output:
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Example 2:
Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Output: []
Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
下面这个代码TLE… 建立edge的过程慢?,深搜也慢,
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <set>
#include <cassert>
using namespace std;
class Solution {
public:
vector<vector<string> > findLadders(string beginWord, string endWord, vector<string> wordList) {
res = vector<vector<string> >();
if(wordList.empty()) return res;
um = unordered_map<string, bool>();
for(auto word: wordList) um[word] = false;
if(um.find(endWord) == um.end()) return res;
if(um.find(beginWord) == um.end()) // beginWord可能不在词表中
wordList.push_back(beginWord);
string word;
edge = unordered_map<string, vector<string> >();
for(int i = 0; i < wordList.size(); ++i){
edge[wordList[i]] = vector<string>();
int len = wordList[i].size();
for(int j = 0; j < len; ++j){
word = wordList[i];
for(char c = 'a'; c <= 'z'; ++c){
word[j] = c;
if(wordList[i] != word && um.find(word) != um.end()){
edge[wordList[i]].push_back(word);
}
}
}
} cur = vector<string>({beginWord}); // initialize list, 等价于 vector<string>(1, beginWord);
um[beginWord] = true; // 永远不会再访问beginWord
cnt = INT_MAX;
helper(beginWord, endWord);
return res;
}
private:
vector<vector<string> > res;
unordered_map<string, vector<string> > edge;
vector<string> cur;
unordered_map<string, bool> um;
int cnt;
inline void helper(string word, string& endWord){
if(word == endWord){
if(cur.size() > cnt) return;
else if(cur.size() == cnt) res.push_back(cur);
else{
cnt = cur.size();
res.clear();
res.push_back(cur);
} return;
} if(cur.size() > cnt) return; // 剪枝
for(auto w: edge[word]){
if(!um[w]){
um[w] = true;
cur.push_back(w);
helper(w, endWord);
um[w] = false;
cur.pop_back();
}
}
}
};
int main(){
//string beginWord = "red", endWord = "tax", arr[] = {"ted","tex","red","tax","tad","den","rex","pee"}; int n = 8;
// string beginWord = "hit", endWord = "cog", arr[] = {"hot","dot","dog","lot","log","cog"}; int n = 6;
string beginWord = "qa", endWord = "sq", arr[] = {"si","go","se","cm","so","ph","mt","db","mb","sb","kr","ln","tm","le","av","sm","ar","ci","ca","br","ti","ba","to","ra","fa","yo","ow","sn","ya","cr","po","fe","ho","ma","re","or","rn","au","ur","rh","sr","tc","lt","lo","as","fr","nb","yb","if","pb","ge","th","pm","rb","sh","co","ga","li","ha","hz","no","bi","di","hi","qa","pi","os","uh","wm","an","me","mo","na","la","st","er","sc","ne","mn","mi","am","ex","pt","io","be","fm","ta","tb","ni","mr","pa","he","lr","sq","ye"};int n = 95;
Solution().findLadders(beginWord, endWord, vector<string>(arr, arr+n));
return 0;
}
这道题题意简单,看似能做,但是考察的比较全面了。
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <set>
#include <cassert>
using namespace std;
class Solution {
public:
vector<vector<string> > findLadders(string beginWord, string endWord, vector<string>& wordList) {
res = vector<vector<string> >();
if(wordList.empty()) return res;
visited = unordered_map<string, bool>();
for(auto word: wordList) visited[word] = false;
if(visited.find(endWord) == visited.end()) return res;
if(visited.find(beginWord) == visited.end()){ // beginWord可能不在词表中
visited[beginWord] = false;
wordList.push_back(beginWord);
}
dis = unordered_map<string, int>();
edge = unordered_map<string, vector<string> >();
string word;
queue<string> q;
q.push(endWord);
dis[endWord] = 0;
visited[endWord] = true;
while(!q.empty()){ // BFS:计算从endWord到beginWord的距离dis
string p = q.front();
// if(p == beginWord) break;
q.pop();
for(int j = 0; j < p.size(); ++j){
word = p;
for(char c = 'a'; c <= 'z'; ++c){
if(c == p[j]) continue;
word[j] = c;
if(visited.find(word) != visited.end() && !visited[word]){
visited[word] = true;
dis[word] = dis[p]+1;
q.push(word);
}
}
}
}
/* 建立edge */
for(int i = 0; i < wordList.size(); ++i){
edge[wordList[i]] = vector<string>();
int len = wordList[i].size();
for(int j = 0; j < len; ++j){
word = wordList[i];
for(char c = 'a'; c <= 'z'; ++c){
word[j] = c;
if(wordList[i][j] != c && visited.find(word) != visited.end()){
edge[wordList[i]].push_back(word);
}
}
}
}
cur = vector<string>({beginWord}); // initialize list, 等价于 vector<string>(1, beginWord);
for(auto it = visited.begin(); it != visited.end(); ++it) it->second = false;
visited[beginWord] = true; // 永远不会再访问beginWord
bestDis = dis[beginWord];
helper(beginWord, endWord);
return res;
}
private:
vector<vector<string> > res;
unordered_map<string, vector<string> > edge;
vector<string> cur;
unordered_map<string, bool> visited;
unordered_map<string, int> dis;
int bestDis;
inline void helper(string word, string& endWord){
if(word == endWord){
res.push_back(cur);
return;
}
for(auto w: edge[word]){
if(!visited[w] && (cur.size()+dis[w] == bestDis)){
visited[w] = true;
cur.push_back(w);
helper(w, endWord);
visited[w] = false;
cur.pop_back();
}
}
}
};
void printv(vector< vector<string> >& res){
for(auto v: res){
for(auto w:v) cout << w << ' ';
cout << endl;
} return;
}
int main(){
//string beginWord = "red", endWord = "tax", arr[] = {"ted","tex","red","tax","tad","den","rex","pee"}; int n = 8;
//string beginWord = "hit", endWord = "cog", arr[] = {"hot","dot","dog","lot","log","cog"}; int n = 6;
string beginWord = "qa", endWord = "sq", arr[] = {"si","go","se","cm","so","ph","mt","db","mb","sb","kr","ln","tm","le","av","sm","ar","ci","ca","br","ti","ba","to","ra","fa","yo","ow","sn","ya","cr","po","fe","ho","ma","re","or","rn","au","ur","rh","sr","tc","lt","lo","as","fr","nb","yb","if","pb","ge","th","pm","rb","sh","co","ga","li","ha","hz","no","bi","di","hi","qa","pi","os","uh","wm","an","me","mo","na","la","st","er","sc","ne","mn","mi","am","ex","pt","io","be","fm","ta","tb","ni","mr","pa","he","lr","sq","ye"};int n = 95;
vector<string> wordList = vector<string>(arr, arr+n);
auto res = Solution().findLadders(beginWord, endWord, wordList);
printv(res);
return 0;
}