Day63 单词接龙

作者: Shimmer_ | 来源:发表于2021-03-31 21:52 被阅读0次

    字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:

    序列中第一个单词是 beginWord 。
    序列中最后一个单词是 endWord 。
    每次转换只能改变一个字母。
    转换过程中的中间单词必须是字典 wordList 中的单词。
    给你两个单词 beginWord 和 endWord 和一个字典 wordList ,找到从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0。

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

    示例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" 不在字典中,所以无法进行转换。

    提示:

    1 <= beginWord.length <= 10
    endWord.length == beginWord.length
    1 <= wordList.length <= 5000
    wordList[i].length == beginWord.length
    beginWord、endWord 和 wordList[i] 由小写英文字母组成
    beginWord != endWord
    wordList 中的所有字符串 互不相同

    Java解法

    思路:

    • 理解起来有些困难,大概意思可以找出以下条件

      • wordlist需要包含除beginWord的所有转换单词
      • 每次更改一个字母,每个字符串位数一定相等
      • 第一次遍历找到可以b->b1的所有单词以及c->c1(倒退),判断b1 c1是否有重合或公有部分进行转换,有则表明最短路径在这些数据当中,否则继续后续遍历
      • ... 多次遍历后,无法匹中时进行,想法有这些,但没有办法输出成算法
    • 不太懂,只能看看官方解,这里抽象成了图的概念(没掌握图相关的知识)

      • 能变化的单词中间构建路径,通过图可以直观看到到达的路径,在通过广度优先搜索处理
    package sj.shimmer.algorithm.m3_2021;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    import java.util.Queue;
    
    /**
     * Created by SJ on 2021/3/31.
     */
    
    class D63 {
        public static void main(String[] args) {
    
        }
    
        Map<String, Integer> wordId = new HashMap<String, Integer>();
        List<List<Integer>> edge = new ArrayList<List<Integer>>();
        int nodeNum = 0;
    
        public int ladderLength(String beginWord, String endWord, List<String> wordList) {
            for (String word : wordList) {
                addEdge(word);
            }
            addEdge(beginWord);
            if (!wordId.containsKey(endWord)) {
                return 0;
            }
            int[] dis = new int[nodeNum];
            Arrays.fill(dis, Integer.MAX_VALUE);
            int beginId = wordId.get(beginWord), endId = wordId.get(endWord);
            dis[beginId] = 0;
    
            Queue<Integer> que = new LinkedList<Integer>();
            que.offer(beginId);
            while (!que.isEmpty()) {
                int x = que.poll();
                if (x == endId) {
                    return dis[endId] / 2 + 1;
                }
                for (int it : edge.get(x)) {
                    if (dis[it] == Integer.MAX_VALUE) {
                        dis[it] = dis[x] + 1;
                        que.offer(it);
                    }
                }
            }
            return 0;
        }
    
        public void addEdge(String word) {
            addWord(word);
            int id1 = wordId.get(word);
            char[] array = word.toCharArray();
            int length = array.length;
            for (int i = 0; i < length; ++i) {
                char tmp = array[i];
                array[i] = '*';
                String newWord = new String(array);
                addWord(newWord);
                int id2 = wordId.get(newWord);
                edge.get(id1).add(id2);
                edge.get(id2).add(id1);
                array[i] = tmp;
            }
        }
    
        public void addWord(String word) {
            if (!wordId.containsKey(word)) {
                wordId.put(word, nodeNum++);
                edge.add(new ArrayList<Integer>());
            }
        }
    }
    
    image

    官方解

    https://leetcode-cn.com/problems/word-ladder/solution/dan-ci-jie-long-by-leetcode-solution/

    1. 广度优先搜索 + 优化建图

      详见链接答案

    2. 双向广度优先搜索

      双向搜索提升效率

    相关文章

      网友评论

        本文标题:Day63 单词接龙

        本文链接:https://www.haomeiwen.com/subject/btaahltx.html