leetcode126. 单词接龙 II

本文介绍了一种解决LeetCode上单词阶梯II问题的方法,通过构建哈希表图并结合宽度优先搜索与深度优先搜索,寻找从beginWord到endWord的所有最短转换序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://leetcode-cn.com/problems/word-ladder-ii/

题意:

按字典 wordList 完成从单词 beginWord 到单词 endWord 转化,一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> ... -> sk 这样的单词序列,并满足:

每对相邻的单词之间仅有单个字母不同。
转换过程中的每个单词 si(1 <= i <= k)必须是字典 wordList 中的单词。注意,beginWord 不必是字典 wordList 中的单词。
sk == endWord
给你两个单词 beginWord 和 endWord ,以及一个字典 wordList 。请你找出并返回所有从 beginWord 到 endWord 的 最短转换序列 ,如果不存在这样的转换序列,返回一个空列表。每个序列都应该以单词列表 [beginWord, s1, s2, ..., sk] 的形式返回。

 方法:哈希表作图,利用宽度搜索遍历所有图的边,利用深度搜索查找所有的最短序列,效率比较低

class Solution {
private:
    vector<vector<string>> ret;//返回的向量
    unordered_map<string,unordered_set<string>> mp;//哈希表作图,<字符串,与它相邻的字符串>
    int minL = 0;//存储最短序列的长度
    void dfs(vector<string> vct,int level,string beginWord)//已经搜索的向量,目前到了第几层,结束的字符串是什么
    {
        string str = vct.back();//存储向量中最后一个元素
        if(level==minL)//如果层数达到了最后一层
        {
            if(str==beginWord)//最后一个单词时起始单词,将向量反转以后插入向量中
            {
                reverse(vct.begin(),vct.end());//反转,使用<algorthm>中的reverse()
                //arrayRever=arrayInt;
                //reverse(arrayRever.begin(),arrayRever.end());
                ret.push_back(vct);//插入返回向量
            }
            else
                return ;//否则直接结束返回
        }
        for(auto iter=mp[str].begin();iter!=mp[str].end();iter++)//继续深搜图中的每一个元素
        {
            vct.emplace_back(*iter);//在这个向量尾部插入图中第i个元素
            dfs(vct,level+1,beginWord);
            vct.pop_back();//把尾部元素删掉,影响下一个元素插入
            //c++可以使用 vector 的成员函数 pop_back() 来删除容器尾部的元素
        }
    }
public:
    vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
        //广搜建图
        queue<pair<string,int>> Q;//用来辅助广搜
        Q.push({beginWord,1});//往队列中插入起始字符串
        unordered_set<string> se;//集合辅助广搜
        for(auto& word:wordList)//更新集合
        {
            se.insert(word);
        }
        se.erase(beginWord);//开始的字符串要删掉
        if(se.find(endWord)==se.end()) return ret;//如果在集合总没找到最后一个字符串,直接返回
        while(!Q.empty())//当队列不为空时,就不停的建图,
        {
            string str = Q.front().first;//取出队首元素的字符串
            int level = Q.front().second;
            Q.pop();//弹出队首元素
            se.erase(str);//在集合中删除对应的字符串
            if(str==endWord&&minL==0)
            {
                minL = level;//标记存在转换序列
                continue ;
            } 
            for(int i=0;i<str.size();i++)
            {
                for(int j=0;j<26;j++)
                {
                    string tmp = str;//暂存字符串,避免str字符串被改变两个字符以上
                    tmp[i] = j+'a';//替换对应的字符,查找集合中是否存在对应的字符串

                    if(se.find(tmp)!=se.end())//如果在集合中的话,就往图里面加边
                    {
                        mp[tmp].insert(str);//key值为tmp对应的哈希项的value向量中插入str,
                        Q.push({tmp,level+1});//队列中插入tmp字符串
                    }
                }
            }
        }
        if(!minL) return ret;//不存在转换序列
        vector<string> vct;//定义最短转换序列的向量
        vct.emplace_back(endWord);//插入最后一个元素
        //深搜找序列,长度达到minL就停止
        dfs(vct,1,beginWord);
        return ret;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值