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.
思路:这是一道BFS的题。保存所有的最短的路径,以下我的解法大数据时超出内存。
class Solution {
public:
bool isLadder(string a, string b) {
int co = 0;
int i;
for (i=0; i<a.size(); ++i) {
if (a[i] != b[i]) {
co++;
}
}
if (co>1) {
return false;
}
return true;
}
struct Data {
<span style="white-space:pre"> </span>string str;
<span style="white-space:pre"> </span>stack<string> strSeq;
<span style="white-space:pre"> </span>Data(string a):str(a) {
<span style="white-space:pre"> </span>strSeq.push(a);
<span style="white-space:pre"> </span>}
};
vector<vector<string> > findLadders(string start, string end, unordered_set<string> &dict) {
vector<vector<string> > res;
vector<string> per;
if (isLadder(start, end)) {
per.push_back(start);
per.push_back(end);
res.push_back(per);
return res;
}
unordered_set<string> myDict = dict;
Data dEnd(end);
queue<Data> pre, back;
back.push(dEnd);
int i,j;
while (!back.empty()) {
<span style="white-space:pre"> </span>while (!pre.empty()) {
<span style="white-space:pre"> </span>pre.pop();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>bool flag = false;
<span style="white-space:pre"> </span>while (!back.empty()) {
<span style="white-space:pre"> </span>Data top = back.front();
<span style="white-space:pre"> </span>back.pop();
<span style="white-space:pre"> </span>for (i=0; i<top.str.size(); ++i) {
<span style="white-space:pre"> </span>for (j=0; j<26; ++j) {
<span style="white-space:pre"> </span>string tmp = top.str;
<span style="white-space:pre"> </span>tmp[i] = 'a' + j;
<span style="white-space:pre"> </span>if ((tmp!=top.str) && (myDict.find(tmp)!=myDict.end())) {
<span style="white-space:pre"> </span>Data dTmp(tmp);
<span style="white-space:pre"> </span>dTmp.strSeq = top.strSeq;
<span style="white-space:pre"> </span>dTmp.strSeq.push(tmp);
<span style="white-space:pre"> </span>pre.push(dTmp);
<span style="white-space:pre"> </span>if (isLadder(tmp, start)) {
<span style="white-space:pre"> </span>flag = true;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>back = pre;
<span style="white-space:pre"> </span>if (flag) {
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>}
}
while (!back.empty()) {
<span style="white-space:pre"> </span>Data top = back.front();
<span style="white-space:pre"> </span>back.pop();
<span style="white-space:pre"> </span>vector<string> vStr;
<span style="white-space:pre"> </span>unordered_set<string> sStr;
<span style="white-space:pre"> </span>vStr.push_back(start);
<span style="white-space:pre"> </span>string cmp = "";
<span style="white-space:pre"> </span>while (!top.strSeq.empty()) {
<span style="white-space:pre"> </span>cmp = top.strSeq.top();
<span style="white-space:pre"> </span>top.strSeq.pop();
<span style="white-space:pre"> </span>vStr.push_back(cmp);
<span style="white-space:pre"> </span>if (sStr.find(cmp) != sStr.end()) {
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>sStr.insert(cmp);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>if ((sStr.size() == vStr.size()-1) && isLadder(cmp, start)) {
<span style="white-space:pre"> </span>res.push_back(vStr);
<span style="white-space:pre"> </span>}
}
/*for (i=0; i<res.size(); ++i) {
<span style="white-space:pre"> </span>for (j=0; j<res[i].size(); ++j) {
<span style="white-space:pre"> </span>cout << res[i][j] << " ";
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>cout << endl;
}*/
return res;
}
};
以上的解法超出了空间限制。改进:可以设一个path,key为当前单词,value表示当前单词的后驱单词。再分别设置变量curStep和nextStep,表示层序变量的上一层和下一层。为了防止字典中的单词多次使用,每比较完一层需要将字典中该层出现过的单词过滤掉。因此代码如下:(代码思路参考了网上的资料)
class Solution {
public:
vector<vector<string> > findLadders(string start, string end, unordered_set<string> &dict) {
map<string,vector<string> > path;
unordered_set<string>rightside=dict;
rightside.erase(start);
unordered_set<string>curStep;
unordered_set<string>nextStep;
curStep.insert(start);
while(curStep.find(end)==curStep.end()&&!rightside.empty())
{
for(auto iter_us_cur=curStep.begin();iter_us_cur!=curStep.end();++iter_us_cur)
{
string temp;
for(int i=0;i<(*iter_us_cur).length();++i)
{
for(int j = 0;j<26;j++)
{
temp = *iter_us_cur;
if(temp[i]!=('a'+j))
{
temp[i] = ('a'+j);
}
if(rightside.find(temp) != rightside.end())
{
nextStep.insert(temp);
if(path.find(*iter_us_cur)==path.end())
{
vector<string> V;
path.insert(make_pair(*iter_us_cur,V));
}
path[*iter_us_cur].push_back(temp);
}
}
}
}
if(nextStep.empty())break;
for(auto iter_set=nextStep.begin();iter_set!=nextStep.end();++iter_set)
{
rightside.erase(*iter_set);
}
curStep = nextStep;
nextStep.clear();
}
vector<vector<string> > result;
vector<string> temp;
if(curStep.find(end)!=curStep.end())
{
output(path,start,end,result,temp);
}
return result;
}
void output(map<string,vector<string> >&path,string start,string end,vector<vector<string> >&result,vector<string> & temp)
{
temp.push_back(start);
if(start==end)
{
result.push_back(temp);return;
}
vector<string>::iterator iter_v;
for(iter_v=path[start].begin();iter_v!=path[start].end();++iter_v)
{
output(path,*iter_v,end,result,temp);temp.pop_back();
}
}
};