1. 程式人生 > >【LeetCode】 127 單詞接龍

【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;
    }
}