【LeetCode】 127 单词接龙

在这里插入图片描述


解题思路:
1 这道题要找一个最短路径,可以联想到图的相关算法(虽然我当时没想到…),那么是不是应该使用最短路径的相关算法呢。其实不用…因为这个图里每条边的长度都是1,用一个广度优先算法就搞定了。
2 规模的问题,如果你遍历List里的每个单词的话,你会发现一直超时,因为有的List的规模给到了上千,每次查找图中的相邻节点都会是一个O(n)。解决办法是对规模很大的List,给每个当前操作单词建立一个“可相邻集”,即把每个字母都替换成其他25个字母,这样的话,两种策略可以保证较好的时间复杂度。

代码:

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        //有效性检查
        if (!wordList.contains(endWord))
            return 0;
        
        Set<String> wordSet = new HashSet(wordList);
        //用于图遍历的队列
        Queue<String> wordsInQ = new LinkedList<>();
        //用于记录路径长度的Map
        Map<String, Integer> pathLength = new HashMap<>();
        //对不同规模的wordList 采取不同策略
        boolean isLarge = wordList.size()>75?true:false;
        
        
        //将开始的单词入队 设置路径长度为1 设置为已访问
        wordsInQ.add(beginWord);
        pathLength.put(beginWord, 1);
        
        while (!wordsInQ.isEmpty()){
            //最前面的单词出队 并获取当前长度
            String nowWord = wordsInQ.poll();
            int nowLength = pathLength.get(nowWord);
            
            if (!isLarge){
                for (String word : wordSet){
                    if (canLad(nowWord, word)){
                        //到终点了 返回长度+1
                        if (word.equals(endWord))
                            return pathLength.get(nowWord) + 1;
                        //word未被访问
                        if (!pathLength.containsKey(word)){
                            pathLength.put(word, nowLength + 1);
                            wordsInQ.add(word);
                        }
                    }
                }
            }else {
                //对当前单词的每个字母进行替换
                for (int i = 0;i < nowWord.length();i++){
                    char[] nowWordArray = nowWord.toCharArray();
                    //替换成其他25个字母
                    for (char j = 'a';j <= 'z';j++){
                        if (nowWordArray[i] == j) continue; 
                        nowWordArray[i] = j;
                        //
                        String word = new String(nowWordArray);
                        // System.out.println(word);
                        //到终点了 返回长度+1
                        if (word.equals(endWord))
                            return pathLength.get(nowWord) + 1;
                        //word在List里且未被访问
                        if (wordSet.contains(word) && !pathLength.containsKey(word)){
                            pathLength.put(word, nowLength + 1);
                            wordsInQ.add(word);
                        }
                    }
                }
            }
        }       
        return 0;
    }
    
    private boolean canLad(String nowWord, String nextWord){
        int length = nowWord.length();
        int times = 0;
        
        for (int i = 0;i < length;i++){
            if (nowWord.charAt(i) != nextWord.charAt(i)){
                times++;
            }
        }
        return times == 1;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_36269372/article/details/84502609