【LeetCode】127. 單詞接龍
一、題目
給定兩個單詞(beginWord 和 endWord)和一個字典,找到從 beginWord 到 endWord 的最短轉換序列的長度。轉換需遵循如下規則:
- 每次轉換隻能改變一個字母。
- 轉換過程中的中間單詞必須是字典中的單詞。
說明:
- 如果不存在這樣的轉換序列,返回 0。
- 所有單詞具有相同的長度。
- 所有單詞只由小寫字母組成。
- 字典中不存在重複的單詞。
- 你可以假設 beginWord 和 endWord 是非空的,且二者不相同。
示例 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、BFS
思路: (主要解釋來自參考2)
先附一下二叉樹的BFS/層序遍歷模板。
public List<List<Integer>> BFS(TreeNode root) {
List<List<Integer>> allResults = new ArrayList<>();
if (root == null) return allResults;
Queue<TreeNode> nodes = new LinkedList<>();
nodes.add(root);
while (!nodes.isEmpty()) {
int levelSize = nodes.size();
List<Integer> results = new ArrayList<>();
for (int i = 0; i < levelSize; i++) {
TreeNode currNode = nodes.poll();
results.add(currNode.val);
if (currNode.left != null) nodes.add(currNode.left);
if (currNode.right != null) nodes.add(currNode.right);
}
allResults.add(results);
}
return allResults;
}
過程:
-
無向圖中兩個頂點之間的最短路徑的長度,可以通過廣度優先遍歷得到;
-
為什麼 BFS 得到的路徑最短?
可以把起點和終點所在的路徑拉直來看,兩點之間線段最短。(想象層層水波往外輻射)
-
可能過程如下圖:
由於程式碼是從a-z
迴圈替換判斷,所以實際替換過程走上半段,即 "hit" -> "hot" -> "dot" -> "dog" -> "cog"
。
程式碼:
class Solution {
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
Queue<String> q = new LinkedList<>();
q.offer(beginWord);
HashSet<String> wordSet = new HashSet<>(wordList);
wordSet.remove(beginWord); // the same as marking visited
int step = 1;
while (!q.isEmpty()) {
int size = q.size();
while (size-- > 0) {
String str = q.poll();
if (str.equals(endWord)) return step; // found shortest transformation path
for (int i = 0; i < str.length(); i++) {
char[] chars = str.toCharArray();
for (char c = 'a'; c <= 'z'; c++) { // try to change 1 character of `str`
chars[i] = c;
String newStr = new String(chars);
if (wordSet.contains(newStr)) {
q.offer(newStr);
wordSet.remove(newStr); // the same as marking visited
}
}
}
}
step++;
}
return 0; // no such transformation sequence.
}
}
時間複雜度:
空間複雜度:
2、Two-ended BFS
思路:
-
已知目標頂點(即終點),可從分別起點和終點執行BFS,直到遍歷有交集,這種方式搜尋的單詞數量會更小點。而且每次可以從單詞數量少的集合開始擴散,以提升速度。
-
這裡 start(visited) 和 end(visited) 交替使用,等價於單向 BFS 裡使用佇列,每次擴散都要加到總的 visited 裡。
程式碼:
class Solution {
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
Set<String> dict = new HashSet<>(wordList);
Set<String> start = new HashSet<>();
Set<String> end = new HashSet<>();
Set<String> visited = new HashSet<>();
// 1. initialize the beginWord
start.add(beginWord);
// 2. all transformed words must be in dict (including endWord)
if (dict.contains(endWord)) end.add(endWord);
// 3. BFS
for (int len = 2; !start.isEmpty(); len++) {
Set<String> current = new HashSet<>();
for (String w : start) {
for (int j = 0; j < w.length(); j++) {
char[] ch = w.toCharArray();
for (char c = 'a'; c <= 'z'; c++) {
if (c == w.charAt(j)) continue; // beginWord and endWord not the same, so bypass itself
ch[j] = c;
String nb = String.valueOf(ch);
if (end.contains(nb)) return len; // meet from two ends
if (dict.contains(nb) && visited.add(nb)) current.add(nb); // not meet yet, visited is safe to use
}
}
}
start = (current.size() < end.size()) ? current : end; // switch to small one to traverse from other end
end = (start == current) ? end : current;
}
return 0;
}
}
時間複雜度:
O
(
26
∗
M
∗
N
)
O(26*M*N)
O(26∗M∗N),M是單詞長度,N是輸入字典表長度。
空間複雜度:
O
(
M
∗
N
)
O(M*N)
O(M∗N)
三、參考
1、單詞接龍
2、廣度優先遍歷、雙向廣度優先遍歷(Java)
3、[Java] BFS Solution - Clean code
4、Simple Java BFS solution with explanation
5、Two-end BFS in Java 31ms.
相關文章
- leetcode 127. 單詞接龍(C++)LeetCodeC++
- LeetCode題解:127. 單詞接龍,雙向BFS,JavaScript,詳細註釋LeetCodeJavaScript
- LeetCode 單詞拆分LeetCode
- 洛谷題單指南-搜尋-P1019 [NOIP2000 提高組] 單詞接龍
- LeetCode-139-單詞拆分LeetCode
- LeetCode-單詞規律LeetCode
- LeetCode-290-單詞規律LeetCode
- LeetCode-079-單詞搜尋LeetCode
- [LeetCode題解]79. 單詞搜尋LeetCode
- LeetCode-434-字串中的單詞數LeetCode字串
- 社群拼團接龍小程式
- leetcode_58_最後一個單詞的長度_簡單LeetCode
- LeetCode-151-翻轉字串裡的單詞LeetCode字串
- 紙牌接龍合集The Zachtronics Solitaire Collection MacAIMac
- 單詞
- [LeetCode] Short Encoding of Words 單詞集的短編碼LeetCodeEncoding
- Leetcode 58. 最後一個單詞的長度LeetCode
- 【leetcode 簡單】第十四題 最後一個單詞的長度LeetCode
- 單詞小卡片 -- 從單詞、例句收集到命令式背單詞
- Win10系統空當接龍游戲在哪裡 win10遊戲空當接龍如何開啟Win10遊戲
- WPF 做一個超級簡單的 1024 數字接龍游戲
- 每日leetcode——42. 接雨水LeetCode
- LeetCode1160.拼寫單詞(Java+暴力+HashMap)LeetCodeJavaHashMap
- [leetcode 30 串聯所有單詞的子串 10ms]LeetCode
- webpack單詞Web
- 單詞拆分
- 單詞遊戲遊戲
- LeetCode每日一題:反轉字串中的單詞 III(No.557)LeetCode每日一題字串
- 【LeetCode】290. Word Pattern 單詞規律(Easy)(JAVA)每日一題LeetCodeJava每日一題
- LeetCode題解(0692):前K個高頻單詞(Python)LeetCodePython
- python爬蟲實現成語接龍1.0Python爬蟲
- 我做了一個成語接龍的小程式
- LeetCode每日一題: 最後一個單詞的長度(No.58)LeetCode每日一題
- 10:單詞排序排序
- android 單詞Android
- 專案接單平臺
- 【Leetcode 346/700】79. 單詞搜尋 【中等】【回溯深度搜尋JavaScript版】LeetCodeJavaScript
- [LeetCode] Substring with Concatenation of All Words 串聯所有單詞的子串LeetCode