leetcode 127. 单词接龙(bfs+建图+最短路)

这篇博客介绍了如何解决LeetCode上的127题——单词接龙。通过将单词映射到编号并构建图,然后使用广度优先搜索(BFS)寻找从beginWord到endWord的最短转换序列。当endWord不在wordList中时,返回0;否则,返回最短路径的步数。示例展示了具体的实现细节和代码片段。
摘要由CSDN通过智能技术生成

题目描述:

题目链接: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;
    }

};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值