题目描述:
题目链接:leetcode 127. 单词接龙
字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:
- 序列中第一个单词是 beginWord 。
- 序列中最后一个单词是 endWord 。
- 每次转换只能改变一个字母。
- 转换过程中的中间单词必须是字典 wordList 中的单词。
给你两个单词 beginWord 和 endWord 和一个字典 wordList ,找到从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0。
示例 1:
输入:beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]
输出:5
解释:一个最短转换序列是 “hit” -> “hot” -> “dot” -> “dog” -> “cog”, 返回它的长度 5。
示例 2:
输入:beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”]
输出:0
解释:endWord “cog” 不在字典中,所以无法进行转换。
提示:
1 <= beginWord.length <= 10
endWord.length == beginWord.length
1 <= wordList.length <= 5000
wordList[i].length == beginWord.length
beginWord、endWord 和 wordList[i] 由小写英文字母组成
beginWord != endWord
wordList 中的所有字符串 互不相同
解法:
整体思路:在能够通过变换一个单词而相互得到两个单词间连一条边,就可以得到一张图。求从 beginWord 到 endWord 的 最短转换序列就转换转换成了求图中beginWord 到 endWord 的最短路径。
具体操作(结合下图理解):
wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]
1.为了方便建图,我们给每个单词按其在wordList中的下标依次编号。由题目可以看出,beginWord并不在wordList中,故应该将其添加到wordList中并统一编号。编号时声明一个unordered_map<string,int>mp,用于存储每个单词和其编号的映射关系。
2.建图:遍历wordList中的单词,尝试将当前单词的每一个依次换成字母 x x x( x x x为小写字母a-z),从而变成一个新单词。假如更换了一个字母的单词存在于wordList中(也即存在于映射关系mp中)就把当前单词和这个新单词间连一条边。
3.求最短路:由于是无权图(也可视作边权为1),用bfs遍历一下图就可以得到最短路。
C++代码:
struct node{
int u; //当前节点编号
int step; //记录路径上地变换次数
};
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
//给单词编号,并建立单词和编号的映射关系:
wordList.push_back(beginWord);
int n=wordList.size();
unordered_map<string,int>mp;
int s=-1,t=-1;
//s、t分别记录beginWord和endWord的编号
for(int i=0;i<n;i++){
if(wordList[i]==beginWord) s=i;
if(wordList[i]==endWord) t=i;
mp.insert(pair<string, int>(wordList[i],i));
}
if(t==-1) return 0; //若endWord不在worList中则不存在相应变换
//建图:
vector<vector<int>>Graph(n,vector<int>());
for(int i=0;i<n;i++){
int len= wordList[i].size();
for(int j=0;j<len;j++){
for(int k=0;k<=25;k++){
string v=wordList[i];
v[j]='a'+k; //逐一地更改当前单词中的字母
unordered_map<string,int>::iterator it;
it=mp.find(v);
//更改了字母地单词如果存在于wordList中,就创建边
if(it!=mp.end()){
Graph[i].push_back((*it).second);
}
}
}
}
//bfs求最短路:
vector<bool>vis(n,false); //记录是否遍历过
queue<node>q;
q.push((node){s,1});
while(!q.empty()){
node now=q.front();
int u=now.u;
int step=now.step;
q.pop();
vis[u]=true;
int l=Graph[u].size();
for(int i=0;i<l;i++){
if(vis[Graph[u][i]]) continue;
if(Graph[u][i]==t) return step+1;
q.push((node){Graph[u][i],step+1});
}
}
return 0;
}
};