- 单词接龙 II
给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:
每次转换只能改变一个字母。
转换后得到的单词必须是字典中的单词。
说明:
如果不存在这样的转换序列,返回一个空列表。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例 1:
输入:
beginWord = “hit”,
endWord = “cog”,
wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]
输出:
[
[“hit”,“hot”,“dot”,“dog”,“cog”],
[“hit”,“hot”,“lot”,“log”,“cog”]
]
示例 2:
输入:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,“dot”,“dog”,“lot”,“log”]
输出: []
解释: endWord “cog” 不在字典中,所以不存在符合要求的转换序列。
题解
很有趣的一个题目吧,我们这样考虑,一开始先把所有的字符串连接起来,就是字符串之间只相差一个字符的进行连接,于是我们得到了一个图,现在对这个图进行BFS广度遍历,不断遍历并且不断标记长度,我们用数组d[5010]进行标记,我们反过来遍历,从endWord反向BFS到beginWord(反向遍历是为了输出答案方便一些),然后得到每个节点的距离后,我们对所有节点跑一遍,如果节点u与节点v相连,并且d[u]=d[v]-1,说明我们最终的答案中一定有一个v->u的答案,不难理解吧,最后再进行一个连接from[u]=v,表示v到了u,然后针对这个动态数组from[u]再进行DFS深度遍历,得到所有答案返回。
AC代码
class Solution {
public:
vector<int>to[5010];
bool check(string s1,string s2)
{
int ans=0;
for(int i=0;i<s1.length();i++)
{
if(s1[i]!=s2[i])ans++;
if(ans>1)return false;
}
return ans==1?true:false;
}
struct Node
{
int id;
int len;
};
queue<Node>q;
bool vis[5010];
int d[5010];
void bfs(int st,vector<string>wordList)
{
vector<string>answer;
while(!q.empty())q.pop();
memset(vis,0,sizeof(vis));
memset(d,0,sizeof(d));
vis[st]=true;
Node t;
t.id=st;
t.len=1;
q.push(t);
while(!q.empty())
{
t=q.front();
q.pop();
d[t.id]=t.len;
for(int i=0;i<to[t.id].size();i++)
{
int v=to[t.id][i];
if(vis[v])continue;
vis[v]=true;
Node w=t;
w.id=v;
w.len=t.len+1;
q.push(w);
}
}
}
vector<int>from[5010];
vector<vector<string>>res;
void dfs(vector<string>path,int st,int et,vector<string>wordList)
{
if(st==et)
{
res.push_back(path);
return;
}
for(int i=0;i<from[st].size();i++)
{
int v=from[st][i];
path.push_back(wordList[v]);
dfs(path,v,et,wordList);
path.pop_back();
}
}
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
wordList.push_back(beginWord);
int sign=-1;
for(int i=0;i<wordList.size();i++)
if(wordList[i]==endWord)
{
sign=i;
break;
}
if(sign==-1)
{
vector<vector<string>>q;
return q;
}
for(int i=0;i<wordList.size();i++)
{
for(int j=i+1;j<wordList.size();j++)
{
if(check(wordList[i],wordList[j]))
{
//cout<<i<<" "<<j<<" here\n";
to[i].push_back(j);
to[j].push_back(i);
}
}
}
bfs(sign,wordList);//标记所有节点到终点距离
for(int i=0;i<wordList.size();i++)
{
for(int j=0;j<to[i].size();j++)
{
int v=to[i][j];
if(d[v]==d[i]-1)//最终的答案肯定包含这样的关系
{
from[i].push_back(v);
}
}
}
memset(vis,0,sizeof(vis));
vector<string>path;
path.push_back(wordList[wordList.size()-1]);
dfs(path,wordList.size()-1,sign,wordList);
return res;
}
};