NO.126 单词接龙

给定两个单词(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" 不在字典中,所以不存在符合要求的转换序列。

1.先将目标字典分类 按biginword到达它们所需变换的次数分层

2.第一次出现endWord 的层级即为搜索终止层级

class Solution {
    //保存最短路径
    int deps=1;
    void DFS(stack<string> &save,string word,string &endWord,unordered_map<string,vector<string>> &connect,vector<vector<string>> &ret)
    {
        save.push(word);
        vector<string>& tmp=connect[word];
        if(save.size()<deps&&tmp.size()>0)
        {
            for(int i=0;i<tmp.size();i++)
            {
                if(tmp[i]==endWord)
                {//保存结果
                    stack<string> target=save;
                    vector<string> copy;
                    copy.push_back(endWord);
                    while(!save.empty())
                    {
                        copy.insert(copy.begin(),save.top());
                        save.pop();
                    }
                    save=target;
                    ret.push_back(copy);
                    break;
                }
                else
                {
                    DFS(save,tmp[i],endWord,connect,ret);
                }
            }
        }
        save.pop();
    }

public:
    vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
        assert(beginWord!=endWord);
        vector<vector<string>> ret;
        //保存该层可匹配的剩余字符串,开始匹配时需将待匹配的字符串从set中移除
        unordered_set<string>all_words(wordList.begin(),wordList.end());
        //endWord不在集合中
        if(all_words.find(endWord)==all_words.end())return ret;

        unordered_set<string>find_set{beginWord};
        //保存字符串可变换的下一个字符串
        unordered_map<string,vector<string>>connect;
        bool find=false;
        while(!find_set.empty()&&!find)
        {
            deps++;
            unordered_set<string> next_set;
            //移除待匹配元素,同层之间不匹配
            for(auto i :find_set)all_words.erase(i);
            for(auto i :find_set)
            {
                string str=i;
                for(int j=0;j<i.size();j++)
                {
                    for(char c_char='a';c_char<='z';c_char++)
                    {//依次变换每一位
                        char old=str[j];
                        if(old!=c_char)
                        {
                            str[j]=c_char;
                            if(all_words.find(str)!=all_words.end())
                            {
                               if(str==endWord)find=true;
                               connect[i].push_back(str);
                               next_set.insert(str);
                            }
                        }
                        str[j]=old;
                    }
                }
            }
            find_set=next_set;
        }
        //cout<<deps<<endl;
        if(!find)return ret;
        stack<string> save;
        DFS(save,beginWord,endWord,connect,ret);
        return ret;
    }
};

执行用时 :164 ms, 在所有C++提交中击败了69.59% 的用户

内存消耗 :22.6 MB, 在所有C++提交中击败了39.50%的用户

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值