給了A、B兩個單詞和一個單詞集合Dict,每個的長度都相同。我們希望通過若干次操作把單詞A變成單詞B,每次操作可以改變單詞中的一個字母,同時,新產生的單詞必須是在給定的單詞集合Dict中。求所有行得通步數最少的修改方法。
舉個例子如下: Given: A = "hit" B = "cog" Dict = ["hot","dot","dog","lot","log"]
Return [ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ]
即把字符串A = "hit"轉變成字符串B = "cog",有以下兩種可能:
"hit" -> "hot" -> "dot" -> "dog" -> "cog";
"hit" -> "hot" -> "lot" -> "log" ->"cog"。
首先把所有的單詞放到一個列表裏面,然後組成一個無相圖,然後從A點開始查找到B點的最短路徑,使用了Dijkstra算法 來查找最短路徑,然後把路徑都打出來。。我用題目的測試用例是通過了,自己寫了幾個測試用例也過了,但是提交以後失敗了。。。汗。。代碼寫得很匆忙。。非常亂哈。。總結一下再發出來,大家做過嗎,都過了麼。。。殘念啊。。。好久沒寫過算法了,,被虐了。。。
#include <string>
#include <vector>
#include <iostream>
#include <set>
#include <map>
#include <algorithm>
using namespace std;
class Solution
{
public:
Solution(){};
//比較函數,比較兩個字符串的差別是否爲1,如果不唯一,返回-1
int cmp(string a,string b)
{
int flag=0;
for(int i= 0; i< a.size(); i++ )
{
if(a[i]!=b[i])
flag++;
if(flag==2)
return -1;
}
if(flag==1)
return 0;
else
return -1;
}
//輔助函數,返回向量中最後一個元素的索引
int last(string str,vector<string> strv)
{
for(int i=0;i<strv.size();i++)
if(str == strv.at(i))
return i;
return -1;
}
//計算路徑
int Size(int a)
{
int b=a;
if(a==0)
return 9999;
else
return b;
}
//輔助函數,顯示
void display(vector< vector< string > > wayList)
{
for(int i=0;i<wayList.size();i++)
{
for(int j=0;j<wayList[i].size();j++)
cout << wayList[i].at(j) << "-->";
cout << endl;
}
}
//主函數
vector< vector<string> > findLadders(string start, string end, set<string>& dict)
{
vector< vector < string > > Res; //返回值
set <string>::iterator si;
int max_len=dict.size()+2; //向量的長度,+2表示起始字符串和結束字符串
/*
二維向量保存各個路徑,第一行表示start字符串,第二行表示end字符串,後面各行表示dict的各個字符串
"hit"-->"hot"...
"hit"-->"dot"
...
...
*/
vector< vector< string > > wayList; //路徑的二維向量,
vector<string> str; //保存所有字符串的向量
if(start == end)
return Res;
/*將數據添加到字符串向量中*/
str.push_back(start);
str.push_back(end);
for (si=dict.begin(); si!=dict.end(); si++)
{
str.push_back(*si);
}
//構造二維向量列的長度
wayList.resize(max_len);
//如果有向量和start只相差一個字符,就將向量添加到二維向量表中
for(int i=0;i<max_len;i++)
{
if(cmp(str.at(0),str.at(i))==0)
{
wayList[i].push_back(str.at(i));
}
}
int flag=0;
while(flag==0)
{
//檢索所有向量
for(int i=0;i<max_len;i++)
{
//不檢索1式因爲1保存的是end
if(i!=1)
{
//檢查所有向量
for(int j=0;j<max_len;j++)
{
//如果該列的向量大於0,表示有一條路徑
if(wayList[i].size()>0)
{
//比較該列最後一個元素是否有相鄰的元素
if(cmp(wayList[i].back(),str.at(j))==0)
{
//如果有,比較這條路徑的長度和已知的路徑長度的大小
if(Size(wayList[j].size())>=Size(wayList[last(wayList[i].back(),str)].size())+1)
{
//如果這條路徑長度小於已知路徑,那將已知路徑刪除,變成這條路徑
wayList[j].clear();
for(int t=0;t<wayList[last(wayList[i].back(),str)].size();t++)
wayList[j].push_back(wayList[last(wayList[i].back(),str)].at(t));
wayList[j].push_back(str.at(j));
//如果索引爲1,表示已經檢索到end字符串,表示已經找出來一條路徑了
if(j==1)
{
//檢查路徑是否重複
for(int m=0;m<Res.size();m++)
{
if(Res.at(m)==wayList[j])
flag=1;
}
//如果不重複,表示路徑正確,添加到返回值中
if(flag==0)
{
vector <string> res;
for(int t=0;t<wayList[j].size();t++)
{
res.push_back(wayList[j].at(t));
}
Res.push_back(res);
}
}//end if(j==1)
}//end if(Size(wayList[j].size())>=Size(wayList[last(wayList[i].back(),str)].size())+1)
}// end if(cmp(wayList[i].back(),str.at(j))==0)
}// end if(wayList[i].size()>0)
}//end for
}// end if(i!=1)
}//end for
//找到重複路徑,表示已經檢索完畢,結束循環
if(flag==1)
break;
}//end while
for(int i=0;i<Res.size();i++)
{
Res[i].insert(Res[i].begin(),start);
}
return Res;
}
};
//start 提示:自動閱卷起始唯一標識,請勿刪除或增加。
int main()
{
//
vector < vector <string> > res;
set <string> strset;
strset.insert("hot");
strset.insert("dot");
strset.insert("dog");
strset.insert("lot");
strset.insert("log");
std::cout << "cog" <<std::endl;
Solution *s=new Solution();
res=s->findLadders("hit","cog",strset);
for(int i=0;i<res.size();i++)
{
for(int j=0;j<res[i].size();j++)
cout << res[i].at(j) << "-->";
cout << " " << endl;
}
return 0;
}
輸出:
hit-->hot-->lot-->log-->cog-->
hit-->hot-->dot-->dog-->cog-->
結果還是失敗。。呵呵。。。