• 【leetcode】Word Ladder II(hard)★ 图 回头看


    Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:

    1. Only one letter can be changed at a time
    2. Each intermediate word must exist in the dictionary

    For example,

    Given:
    start = "hit"
    end = "cog"
    dict = ["hot","dot","dog","lot","log"]

    Return

      [
        ["hit","hot","dot","dog","cog"],
        ["hit","hot","lot","log","cog"]
      ]

    思路:

    我自己用回溯做,结果超时了。代码和注释如下: 很长

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <unordered_set>
    #include <string>
    using namespace std;
    
    class Solution {
    public:
        vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
            vector<vector<string>> ans;
            vector<string> hash; //记录单词是否已经生成
            vector<string> X;
            vector<vector<string>> S;
            vector<int> hashlength; //记录在k = 0 - ... 时 hash 的长度 方便弹出
    
            int minlen = 1000;
            int k = 0;
            hash.push_back(start);
            hashlength.push_back(1);
            if(S.size() <= k)
            {
                S.push_back(vector<string>());
            }
            S[k].push_back(start);
    
            while(k >= 0)
            {
                while(!S[k].empty())
                {
                    X.push_back(S[k].back());
                    S[k].pop_back();
    
                    if(onedifferent(X.back(), end))
                    {
                        X.push_back(end);
                        if(k == minlen) //只存长度最短的
                        {
                            ans.push_back(X);
                        }
                        if(k < minlen) //如果有新的最短长度 ans清空,压入新的最短答案
                        {
                            minlen = k;
                            ans.clear();
                            ans.push_back(X);
                        }
                    }
                    else if(k < minlen) //k如果>= minlen 那么后面的结果肯定大于最短长度
                    {
                        k++;
                        if(S.size() <= k) //如果S的长度不够 扩大S长度
                        {
                            S.push_back(vector<string>());
                        }
                        if(hashlength.size() <= k)//如果hashlength的长度不够 扩大其长度
                        {
                            hashlength.push_back(0);
                        }
                        unordered_set<string>::iterator it;
                        for(it = dict.begin(); it != dict.end(); it++) //对字典中的数字遍历,得到下一个长度可以用的备选项
                        {
                            if(onedifferent(X.back(), *it) && (find(hash.begin(), hash.end(), *it) == hash.end()))
                            {
                                hashlength[k]++;
                                hash.push_back(*it);
                                S[k].push_back(*it);
                            }
                        }
                    }
                }
                k--;
                while(k >= 0 && hashlength[k]) //把当前层压入hash的值都弹出
                {
                    hash.pop_back();
                    hashlength[k]--;
                }
                while(k >= 0 && X.size() > k) //把当前层压入X的值弹出
                {
                    X.pop_back();
                }
            }
    
            return ans;
        }
    
        bool onedifferent(string s1, string s2) //判断s1是否可以只交换一次得到s2
        {
            int diff = 0;
            for(int i = 0; i < s1.size(); i++)
            {
                if(s1[i] != s2[i])
                    diff++;
            }
            return (diff == 1);
        } 
    };
    
    int main()
    {
        Solution s;
        unordered_set<string> dict;
        dict.insert("hot");
        dict.insert("dot");
        dict.insert("dog");
        dict.insert("lot");
        dict.insert("log");
    
        string start = "hit";
        string end = "cog";
    
        vector<vector<string>> ans = s.findLadders(start, end, dict);
    
        return 0;
    }

    别人的思路:我没怎么看,只知道是用图的思想 速度也不快 差不多1000ms的样子

    class Solution {
    public:
        vector<vector<string>> helper(unordered_map<string,vector<string>> &pre,string s,unordered_map<string,int>&visit,string start){
            vector<vector<string> > ret,ret1;vector<string> t_ret;
            if(s==start) {t_ret.push_back(s);ret.push_back(t_ret);return ret;}
            for ( auto it = pre[s].begin(); it != pre[s].end(); ++it ){
                ret1=helper(pre,*it,visit,start);
                for(int i=0;i<ret1.size();i++){
                    ret1[i].push_back(s);
                    ret.push_back(ret1[i]);
                } ret1.clear();
            }
            return ret;
        }
        vector<vector<string>> findLadders(string start, string end, unordered_set<string> &dict) {
            unordered_map<string,vector<string> > graph;unordered_map<string,int> visit;unordered_map<string,vector<string>> pre;
            vector<vector<string> > ret; vector<string> t_ret;
            if(start==end){t_ret.push_back(start);t_ret.push_back(end);ret.push_back(t_ret);return ret;}
            dict.insert(start);dict.insert(end);
            for ( auto it = dict.begin(); it != dict.end(); ++it ){
                string t=*it; visit[t]=0;
                for(int i=0;i<t.size();i++)
                    for(int j='a';j<='z';j++){
                        if(char(j)==t[i]) continue;
                        string tt=t;
                        tt[i]=char(j);
                        if(dict.count(tt)>0) graph[t].push_back(tt);
                    }
            }
            queue <string> myq;
            myq.push(start);
            while(!myq.empty()){
                for(int i=0;i<graph[myq.front()].size();i++){
                    if( visit[graph[myq.front()][i]]==0){
                        visit[graph[myq.front()][i]]=visit[myq.front()]+1;
                        myq.push(graph[myq.front()][i]);
                        pre[graph[myq.front()][i]].push_back(myq.front());
                    }
                    else if(visit[graph[myq.front()][i]]>0&&visit[graph[myq.front()][i]]>=visit[myq.front()]+1){
                        if(visit[graph[myq.front()][i]]>visit[myq.front()]+1){
                            visit[graph[myq.front()][i]]=visit[myq.front()]+1;
                             pre[graph[myq.front()][i]].push_back(myq.front());
                        }else  pre[graph[myq.front()][i]].push_back(myq.front());;
                    }
                }
                visit[start]=1;
                myq.pop();
            }
            if(visit[end]==0) return ret; 
            ret=helper(pre,end,visit,start);
            return ret;
        }
    };
  • 相关阅读:
    .NET数据库编程求索之路11.一些思考
    VMware Workstation安装使用手记
    VS2010无法保存项目文件(.csprj)的问题解决方法
    【转】VC++/MFC(VC6)开发技术精品学习资料下载汇总 (2011.3.10更新)
    .NET数据库编程求索之路9.使用EF实现
    oracle11g新特性:闪回数据归档(Flashback Data Archive)#ocp试验#
    ORACLE口令文件验证与操作系统验证|转|
    闪回flashback#ocp试验#
    expdp数据泵导出操作
    手动模式下热备份的不完全恢复#OCP试验#
  • 原文地址:https://www.cnblogs.com/dplearning/p/4240364.html
Copyright © 2020-2023  润新知