zoukankan      html  css  js  c++  java
  • (Java) LeetCode 127. Word Ladder —— 单词接龙

    Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:

    1. Only one letter can be changed at a time.
    2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

    Note:

    • Return 0 if there is no such transformation sequence.
    • All words have the same length.
    • All words contain only lowercase alphabetic characters.
    • You may assume no duplicates in the word list.
    • You may assume beginWord and endWord are non-empty and are not the same.

    Example 1:

    Input:
    beginWord = "hit",
    endWord = "cog",
    wordList = ["hot","dot","dog","lot","log","cog"]
    
    Output: 5
    
    Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
    return its length 5.

    Example 2:

    Input:
    beginWord = "hit"
    endWord = "cog"
    wordList = ["hot","dot","dog","lot","log"]
    
    Output: 0
    
    Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.

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

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

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


    Java

    class Solution {
        public int ladderLength(String beginWord, String endWord, List<String> wordList) {
            HashSet<String> wordSet = new HashSet<>(wordList); //替换掉题目中List结构,加速查找
            if (!wordSet.contains(endWord)) return 0; //如果目标顶点不在图中,直接返回0
            HashMap<String, Integer> map = new HashMap<>(); //用来存储已访问的节点,并存储其在路径上的位置,相当于BFS算法中的isVisted功能
            Queue<String> q = new LinkedList<>(); //构建队列,实现广度优先遍历
            q.add(beginWord); //加入源顶点
            map.put(beginWord, 1); //添加源顶点为“已访问”,并记录它在路径的位置
            while (!q.isEmpty()) { //开始遍历队列中的顶点
                String word = q.poll(); //记录现在正在处理的顶点
                int level = map.get(word); //记录现在路径的长度
                for (int i = 0; i < word.length(); i++) {
                    char[] wordLetter = word.toCharArray();
                    for (char j = 'a'; j <= 'z'; j++) {
                        if (wordLetter[i] == j) continue; 
                        wordLetter[i] = j; //对于每一位字母,分别替换成另外25个字母
                        String check = new String(wordLetter);
                        if (check.equals(endWord)) return map.get(word) + 1; //如果已经抵达目标节点,返回当前路径长度+1
                        if (wordSet.contains(check) && !map.containsKey(check)) { //如果字典中存在邻接节点,且这个邻接节点还未被访问
                            map.put(check, level + 1); //标记这个邻接节点为已访问,记录其在路径上的位置
                            q.add(check); //加入队列,以供广度搜索
                        }
                    }
                }
            }
            return 0;
        }
    }
  • 相关阅读:
    Webservice详解
    Spring IOC/DI和AOP原理
    MySQL 使用JOIN优化子查询
    MySQL 更新语句技巧
    MySQL插入语句解析
    MySQL用户无法登陆问题
    MySQL基础学习(二) 常用SQL命令
    Servlet/JSP-08 EL表达式
    插值和空间分析(一)_探索性数据分析(R语言)
    爱重启的windows,伤不起
  • 原文地址:https://www.cnblogs.com/tengdai/p/9249543.html
Copyright © 2011-2022 走看看