【LeetCode】 127 單詞接龍
阿新 • • 發佈:2018-11-29
解題思路:
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; } }