• LeetCode 126 单词接龙 II


    这道题是给出起始的单词和最终的单词,再给出一个单词列表,问从起始的单词转换成最终的单词最少需要转换次数的步骤,可能有多个符合要求的答案,都要输出。如果两个单词只有一位的字母不同,则这两个单词可以转换。思路就是首先用map把单词都映射为int,然后把每个单词看作一个点,两个可以互相转换的单词连一条线,就构成了图,如果最终的单词不在图里可以直接输出。接下来就是难点了,因为这道题本质就是求最短路径,但是有可能有多条最短路径。我首先尝试了dfs回溯,结果超时,又进行剪枝,还是超时,又试了一些bfs改进打的方法,都是超时。看了题解,才知道用改进的bellman-ford可以求出,把数列中保存的点改成保存点的数组,这就相当于记录了路径,如果数组最后一个元素是最终的单词,即可把这个数组添加到答案,因为这个算法已经可以保证路径最短。

    class Solution {
    public:
    
        vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
            int sz=wordList.size(),len=beginWord.size();
            vector<int> G[sz+5];
            vector<vector<string> > ans;
            unordered_map<string,int> mp;
            unordered_map<int,string> cg;
            int vis[sz+5],d[sz+5];
            memset(vis,0,sizeof(0));
            int cnt = 1;
            mp[beginWord]=cnt++;
            cg[cnt-1]=beginWord;
            for(int i=0;i<sz;i++)
            {
                if(!mp[wordList[i]]) 
                {
                    mp[wordList[i]]=cnt++;
                    cg[cnt-1]=wordList[i];
                }
                else continue;
                int ok=0;
                for(int j=0;j<len;j++)
                if(beginWord[j]!=wordList[i][j])
                {
                    ok++;
                    if(ok>1) break;
                }
                if(ok==1) G[1].push_back(mp[wordList[i]]);
            }
            for(int i=0;i<sz;i++)
                if(wordList[i]!=beginWord)
                    for(int j=i+1;j<sz;j++)
                        if(wordList[j]!=beginWord)
                        {
                            int ok=0;
                            for(int k=0;k<len;k++)
                            if(wordList[i][k]!=wordList[j][k])
                            {
                                ok++;
                                if(ok>1) break;
                            }
                            if(ok==1) 
                            {
                                G[mp[wordList[i]]].push_back(mp[wordList[j]]);
                                G[mp[wordList[j]]].push_back(mp[wordList[i]]);
                            }
                        }
            if(!mp[endWord]) return ans;
            memset(d,0x3f3f3f3f,sizeof(d));
            vector<int> v,now;
            v.push_back(1);
            queue<vector<int> > q;
            d[1]=0;
            q.push(v);
            int goal = mp[endWord];
            while(!q.empty())
            {
                now=q.front();q.pop();
                int b=now.back();
                if(b==goal)
                {
                    vector<string> vs;
                    for(int i=0;i<now.size();i++)
                    vs.push_back(cg[now[i]]);
                    ans.push_back(vs);
                    continue;
                }
                for(int i=0;i<G[b].size();i++)
                {
                    int v=G[b][i];
                    if(d[v]>=d[b]+1)
                    {
                        d[v]=d[b]+1;
                        vector<int> tmp(now);
                        tmp.push_back(v);
                        q.push(tmp);
                    }
                }
            }
            return ans;
        }
    };
    
  • 相关阅读:
    this指向
    this指向
    this指向
    this指向
    a=b=c 连等赋值的分析
    测试应用documentFragment 和 直接操作dom 的区别
    javascript 基本数据类型、引用数据类型
    判断一个变量的具体类型 的终极方案
    判断变量是否为 NaN
    C#稳固基础:传统遍历与迭代器
  • 原文地址:https://www.cnblogs.com/ambition-hhn/p/13060234.html
Copyright © 2020-2023  润新知