• Leetcode 127.单词接龙


    单词接龙

    给定两个单词(beginWord endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:

    1. 每次转换只能改变一个字母。
    2. 转换过程中的中间单词必须是字典中的单词。

    说明:

    • 如果不存在这样的转换序列,返回 0。
    • 所有单词具有相同的长度。
    • 所有单词只由小写字母组成。
    • 字典中不存在重复的单词。
    • 你可以假设 beginWordendWord 是非空的,且二者不相同。

    示例 1:

    输入:

    beginWord = "hit",

    endWord = "cog",

    wordList = ["hot","dot","dog","lot","log","cog"]

    输出: 5

    解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",

    返回它的长度 5。

    示例 2:

    输入:

    beginWord = "hit"

    endWord = "cog"

    wordList = ["hot","dot","dog","lot","log"]

    输出: 0

    解释: endWord "cog" 不在字典中,所以无法进行转换。

    这是很典型的单源头广度优先搜索最短路径的问题,只要想到这里,结合图的知识就很好做了。怎么构建图呢?首先图的顶点显而易见,就是每一个单词。那么顶点之间的边呢?就是如果顶点的单词互相只差一个字母,顶点间就会形成边。用第一个例子绘制的图如下:

    那么根据广度优先搜索的步骤,构建一个队列,之后先把源顶点加入队列,以队列是否为空作为条件开始循环:如果队列不为空,逐个取出队列中的顶点,并把它们标记为"已访问"。对于每个取出的顶点,依次把它未访问的顶点加入队列,直到找到目标顶点或者所有顶点都访问完毕。因为此题只是求最短路径的长度,而不是路径上都有哪些顶点,所以只需要存储每访问一个顶点时该顶点处在路径的位置即可。这里我用了HashMap<String, Integer>。如果是需要存储最短路径本身,那么需要建立数据结构依次存储每个顶点的前驱,并在最后追溯前驱获得路径上的所有顶点。

    这里我用一个HashSet替换掉题目中存储单词的List数据结构,只是为了搜索的时候能够快一点。至于如何获取某个节点的邻接节点,即和它只差一个字母的单词,这里用了最暴力的办法,就是把顶点单词的每一位换成其他的25个字母,看看它在不在题目提供的字典里。详细的标注都已经标注在代码中,见下。

     1 class Solution{
     2     public int ladderLength(String beginWord,String endWord,List<String> wordList){
     3         HashSet<String> wordSet=new HashSet<>(wordList);//替换题目中List结构,加速查找
     4         if(!wordSet.contains(endWord)) return 0;
     5         HashMap<String,Integer> map=new HashMap<>();//用来存储已访问的节点,并存储其在路径上的位置,相当于BFS算法中的isVisted功能
     6         Queue<String> q=new LinkedList<>();//构建队列,实现广度优先遍历。
     7         q.add(beginWord);//加入源顶点
     8         map.put(beginWord,1);//添加原顶点为“已访问”,并记录它在路径的位置
     9         while(!q.isEmpty()){
    10             String word=q.poll();//记录正在处理的顶点
    11             int level=map.get(word);//记录现在路径的长度
    12             for(int i=0;i<word.length();i++){
    13                 char[] wordLetter=word.toCharArray();
    14                 for(char j='a';j<='z';j++){
    15                     if(wordLetter[i]==j) continue;
    16                     wordLetter[i]=j;//对于每一位字母,分别替换成另外25个字母
    17                     String check=new String(wordLetter);
    18                     if(check.equals(endWord)) return map.get(word)+1;//如果已经抵达目标节点,返回当前路径长度+1
    19                     if(wordSet.contains(check)&&!map.containsKey(check)){//如果字典中存在邻接节点,且这个邻接节点还未被访问
    20                         map.put(check,level+1);//标记这个邻接节点为已访问,记录其在路径上的位置
    21                         q.add(check);//加入队列,以供广度搜索
    22                     }
    23                 }
    24             }
    25         }
    26         return 0;
    27     }
    28 }
  • 相关阅读:
    php程序去除文件 bom头
    类继承接口后,实现接口的方法
    virtual和abstract的使用场景分别是什么?待更新。
    get请求和post请求的总结
    ES6新语法,持续更新
    display:flex中的不懂的问题,待处理
    css相邻兄弟选择器(+),伪类(:hover),伪元素(::after)
    HTML中的input的type类型
    命令行打开程序的集合
    sqlserver 常用的语句
  • 原文地址:https://www.cnblogs.com/kexinxin/p/10187802.html
Copyright © 2020-2023  润新知