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"] ]
本题5星难度,和I一样用bfs,但是因为要输出,所以时间不够
先遍历找到每个词的前驱词,用两个队列保存当前层和之前层的词,一个是正在处理,一个是下次需要处理
得到前驱词表后,从end往前递归打印路径
AC代码
class Solution {
public:
vector< vector< string> > res;
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &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<vector<string>> findLadders(string start, string end, unordered_set<string> &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<string> &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;
}
};