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"]
]
思路:
我自己用回溯做,结果超时了。代码和注释如下: 很长
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <stack>
#include <unordered_set>
#include <string>
using namespace std; class Solution {
public:
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
vector<vector<string>> ans;
vector<string> hash; //记录单词是否已经生成
vector<string> X;
vector<vector<string>> S;
vector<int> hashlength; //记录在k = 0 - ... 时 hash 的长度 方便弹出 int minlen = ;
int k = ;
hash.push_back(start);
hashlength.push_back();
if(S.size() <= k)
{
S.push_back(vector<string>());
}
S[k].push_back(start); while(k >= )
{
while(!S[k].empty())
{
X.push_back(S[k].back());
S[k].pop_back(); if(onedifferent(X.back(), end))
{
X.push_back(end);
if(k == minlen) //只存长度最短的
{
ans.push_back(X);
}
if(k < minlen) //如果有新的最短长度 ans清空,压入新的最短答案
{
minlen = k;
ans.clear();
ans.push_back(X);
}
}
else if(k < minlen) //k如果>= minlen 那么后面的结果肯定大于最短长度
{
k++;
if(S.size() <= k) //如果S的长度不够 扩大S长度
{
S.push_back(vector<string>());
}
if(hashlength.size() <= k)//如果hashlength的长度不够 扩大其长度
{
hashlength.push_back();
}
unordered_set<string>::iterator it;
for(it = dict.begin(); it != dict.end(); it++) //对字典中的数字遍历,得到下一个长度可以用的备选项
{
if(onedifferent(X.back(), *it) && (find(hash.begin(), hash.end(), *it) == hash.end()))
{
hashlength[k]++;
hash.push_back(*it);
S[k].push_back(*it);
}
}
}
}
k--;
while(k >= && hashlength[k]) //把当前层压入hash的值都弹出
{
hash.pop_back();
hashlength[k]--;
}
while(k >= && X.size() > k) //把当前层压入X的值弹出
{
X.pop_back();
}
} return ans;
} bool onedifferent(string s1, string s2) //判断s1是否可以只交换一次得到s2
{
int diff = ;
for(int i = ; i < s1.size(); i++)
{
if(s1[i] != s2[i])
diff++;
}
return (diff == );
}
}; int main()
{
Solution s;
unordered_set<string> dict;
dict.insert("hot");
dict.insert("dot");
dict.insert("dog");
dict.insert("lot");
dict.insert("log"); string start = "hit";
string end = "cog"; vector<vector<string>> ans = s.findLadders(start, end, dict); return ;
}
别人的思路:我没怎么看,只知道是用图的思想 速度也不快 差不多1000ms的样子
class Solution {
public:
vector<vector<string>> helper(unordered_map<string,vector<string>> &pre,string s,unordered_map<string,int>&visit,string start){
vector<vector<string> > ret,ret1;vector<string> t_ret;
if(s==start) {t_ret.push_back(s);ret.push_back(t_ret);return ret;}
for ( auto it = pre[s].begin(); it != pre[s].end(); ++it ){
ret1=helper(pre,*it,visit,start);
for(int i=;i<ret1.size();i++){
ret1[i].push_back(s);
ret.push_back(ret1[i]);
} ret1.clear();
}
return ret;
}
vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
unordered_map<string,vector<string> > graph;unordered_map<string,int> visit;unordered_map<string,vector<string>> pre;
vector<vector<string> > ret; vector<string> t_ret;
if(start==end){t_ret.push_back(start);t_ret.push_back(end);ret.push_back(t_ret);return ret;}
dict.insert(start);dict.insert(end);
for ( auto it = dict.begin(); it != dict.end(); ++it ){
string t=*it; visit[t]=;
for(int i=;i<t.size();i++)
for(int j='a';j<='z';j++){
if(char(j)==t[i]) continue;
string tt=t;
tt[i]=char(j);
if(dict.count(tt)>) graph[t].push_back(tt);
}
}
queue <string> myq;
myq.push(start);
while(!myq.empty()){
for(int i=;i<graph[myq.front()].size();i++){
if( visit[graph[myq.front()][i]]==){
visit[graph[myq.front()][i]]=visit[myq.front()]+;
myq.push(graph[myq.front()][i]);
pre[graph[myq.front()][i]].push_back(myq.front());
}
else if(visit[graph[myq.front()][i]]>&&visit[graph[myq.front()][i]]>=visit[myq.front()]+){
if(visit[graph[myq.front()][i]]>visit[myq.front()]+){
visit[graph[myq.front()][i]]=visit[myq.front()]+;
pre[graph[myq.front()][i]].push_back(myq.front());
}else pre[graph[myq.front()][i]].push_back(myq.front());;
}
}
visit[start]=;
myq.pop();
}
if(visit[end]==) return ret;
ret=helper(pre,end,visit,start);
return ret;
}
};