zoukankan      html  css  js  c++  java
  • 127. 单词接龙 力扣(困难) bfs+建图 无法高效建图

    题目描述;

    字典 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。

    概念:

    双向BFS:

    如果使用两个同时进行的广搜可以有效地减少搜索空间。一边从 beginWord 开始,另一边从 endWord 开始。我们每次从两边各扩展一层节点,当发现某一时刻两边都访问过同一顶点时就停止搜索。这就是双向广度优先搜索,它可以可观地减少搜索空间大小,从而提高代码运行效率。

    学习知识:

    可以将vector中的输入,放入set中,更容易查询

    unordered_set<string> ss(wordList.begin(),wordList.end());

    题解:

    因为有5000个单词,如果两两单词之间找关系,无疑超时,考虑到每个单词最多也就10*25种状态,枚举,不构图。

    题源:https://leetcode-cn.com/problems/word-ladder/

    代码:

    class Solution {
    public:
     
        int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        
        queue<string> Q1,Q2;
        unordered_map<string,int> mp1;
        unordered_map<string,int> mp2;
        int res=0;
    
        for(string i : wordList) {mp1[i]=-1; mp2[i]=-1;}
        if(mp1.find(endWord)==mp1.end() ) return 0;   //如果没有结束单词的状态,直接返回0
    
        mp1[beginWord]=1;
        mp2[endWord]=1;
        Q1.push(beginWord);
        Q2.push(endWord);
        while(!Q1.empty() && !Q2.empty())
        {
           if (Q1.size()>Q2.size()) {Q1.swap(Q2); mp1.swap(mp2); }   //优先遍历节点数少的
           for(int t=Q1.size();t>0;t--)
           {
                string p=Q1.front();
                Q1.pop();
                for(int i=0;i<p.length();i++)    // 必须遍历一整层,才叫双向bfs
                {
                    for(int j=0;j<26;j++)
                    {
                        char ch='a'+j;
                        if(ch==p[i]) continue;
                        string newp=p;
                        newp[i]=ch;
                        if(mp1.find(newp)==mp1.end() || mp1[newp]>=0) continue;   //如果不存在newp中间状态,或者该方向bfs已经访问过,则continue
                        if(mp2.find(newp)!=mp2.end() && mp2[newp]>=0)   //  如果该状态在另个方向bfs时已经访问过,结果就出来了
                            {res=mp1[p]+mp2[newp]; break;}
                        mp1[newp]=mp1[p]+1;       // 否则加入队列中
                        Q1.push(newp);
                    }
                    if(res) break;
                }
                if(res) break;
           }
           if(res) break;
        }
         return res;
        }
    };
  • 相关阅读:
    Head First设计模式(观察者模式Observer)
    Head First设计模式(装饰者模式)
    Head First设计模式
    Head First设计模式 单件模式 独一无二的对象
    .NET 设计规范.NET约定、惯用法与模式8.使用规范
    .NET 设计规范.NET约定、惯用法与模式附录:C#编程风格约定
    设计模式 一 引言
    .NET 设计规范.NET约定、惯用法与模式7.异常
    Head First设计模式 工厂模式 烘烤OO的精华
    前端IDE中Emmet插件快捷输入HTML代码
  • 原文地址:https://www.cnblogs.com/stepping/p/15018862.html
Copyright © 2011-2022 走看看