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"]
]
本題5星難度,和I一樣用bfs,但是因為要輸出,所以時間不夠
先遍歷找到每個詞的前驅詞,用兩個隊列保存當前層和之前層的詞,一個是正在處理,一個是下次需要處理
得到前驅詞表後,從end往前遞歸打印路徑
AC代碼
class Solution {
public:
vector< vector< string> > res;
vector> findLadders(string start, string end, unordered_set &dict) {
dict.insert(start);
dict.insert(end);
unordered_map< string, vector< string> > precursor;//保存每個詞對應的前驅詞
for( unordered_set< string>::const_iterator citer = dict.begin(); citer != dict.end(); ++citer)//初始化
precursor.insert( make_pair( *citer, vector< string>()));
vector< unordered_set< string> >layers(2);//分別用來保存當前層的詞和之前層的詞
layers[0].insert(start);
int cur = 0;
int pre = 1;
while(true){
cur = !cur;//兩層互換
pre = !pre;
for( unordered_set< string>::const_iterator citer = layers[pre].begin(); citer != layers[pre].end(); ++citer)
dict.erase(*citer);//刪除之前層裡出現在字典裡的詞
layers[cur].clear();
//bfs搜索之前層裡每個詞通過一次變換可以達到的詞,該詞如果在字典裡就放入當前層
for( unordered_set< string>::const_iterator citer = layers[pre].begin(); citer != layers[pre].end(); ++citer){
string str = *citer;
for( int i = 0; i < str.size(); ++i){
for( int j = 'a'; j <= 'z'; ++j){
if( str[i] == j)
continue;
string tmp = str;
tmp[i] = j;
if( dict.count(tmp)){
precursor[tmp].push_back(str);
layers[cur].insert(tmp);
}
}
}
}
if( layers[cur].empty())//如果當前層空,說明無法從start到end,結束
return res;
if( layers[cur].count(end))//如果當前層出現end,說明已經找到了轉換,而且因為是根據層數來的,所以都是shortest
break;
}
vector< string> path;
generatePath( precursor, path, end);
return res;
}
//從end開始從後往前遞歸
void generatePath( unordered_map< string, vector< string> > &precursor, vector< string> &path, string end){
if( precursor[end].size() == 0){//沒有前驅詞說明已經到了start
path.push_back(end);
vector< string> tmp = path;
reverse( tmp.begin(), tmp.end());//反轉次序
res.push_back(tmp);
path.pop_back();
}
path.push_back(end);
for( vector< string>::const_iterator citer = precursor[end].begin(); citer != precursor[end].end(); ++citer){
generatePath( precursor, path, *citer);
}
path.pop_back();
}
}; TLE得一塌糊塗,還是不能用遞歸的
class Solution {
public:
vector> findLadders(string start, string end, unordered_set &dict) {
vector< vector< string> > res;
vector< string> cur;
cur.push_back(start);
dict.insert(end);
unordered_set< string> tmp = dict;
int length = ladderLength(start, end, tmp);
core( res, cur, start, end, dict, length);
return res;
}
void core( vector< vector< string> > &res, vector< string> &cur, string start, string end, unordered_set< string> &dict, int l){
if( cur.size() > l)
return;
if( start == end){
res.push_back(cur);
return;
}
for( int i = 0; i < start.size(); ++i){
for( int j = 'a'; j <= 'z'; ++j){
if( start[i] == j)
continue;
else{
string tmp = start;
tmp[i] = j;
if( dict.count(tmp)){
cur.push_back(tmp);
dict.erase(tmp);
core( res, cur, tmp, end, dict, l);
cur.pop_back();
dict.insert(tmp);
}
}
}
}
}
int ladderLength(string start, string end, unordered_set &dict) {
int shortest = INT_MAX;
dict.insert(end);
queue< pair< string, int> > q;
q.push( pair< string, int>( start, 1));
while( !q.empty()){
pair< string, int> cur = q.front();
q.pop();
if( cur.first == end){
shortest = shortest < cur.second ? shortest : cur.second;
continue;
}
string str = cur.first;
for( int i = 0; i < str.size(); ++i){
for( int j = 'a'; j <= 'z'; ++j){
if( str[i] == j)
continue;
string tmp = str;
tmp[i] = j;
if( dict.count(tmp)){
q.push( make_pair( tmp, cur.second+1));
dict.erase(tmp);
}
}
}
}
if( shortest == INT_MAX)
return 0;
return shortest;
}
};