[LeetCode]Word Ladder,解題報告
目錄
題目
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:
- Only one letter can be changed at a time
- Each intermediate word must exist in the dictionary
For example,
Given:
start = “hit”
end = “cog”
dict = [“hot”,”dot”,”dog”,”lot”,”log”]
As one shortest transformation is “hit” -> “hot” -> “dot” -> “dog” -> “cog”,
return its length 5.
Note:
- Return 0 if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
思路
這道題目本身不難,但是很考察每個做題人的抽象能力。因為之前我在《程式設計之美》上看到過這個題目,所以我很快的能把這道題跟多叉樹聯絡在一起。
我們假設start字串為多叉樹的根節點,end字串為多叉樹最後的葉子節點。那當start字串改變其中一個字元形成的新字串new,並且new屬於dict字典當中,那new字串就是start的第一個子節點。其他節點以此類推。
當我們把這道題目想成一個多叉樹之後,接下來我們要做的就是從根節點開始,找一條能走到end節點的路徑。遍歷的方法有:BFS和DFS,從時間角度考慮,我們當然選擇BFS。
AC程式碼
有人在明白了抽象成多叉樹之後,依然可能面臨TLE的問題。
原因:通常我們入佇列的方式是從dict字典裡選一個字串,判斷和當前字串是否相差一個字元,是則入佇列,不是,則不入佇列。這樣的時間複雜度是O(n),n是字典的數量。當n很大時,就容易TLE。
解決方案:我們可以換一種思路,英文字母一共26個,當前字串的長度是L,所以我們用26個英文字母對當前字串的每個字元挨個替換,看形成的新字串是否在字典中。是則入佇列,不是則不入佇列。這樣的時間複雜度是:O(L* 26)。這樣親測,不超時。
public class Solution {
public static int ladderLength(String start, String end, Set<String> dict) {
int dist = calDistance(start, end);
if (dist == 1) {
return 2;
}
return bfsDict(dict, start, end);
}
private static int calDistance(String word1, String word2) {
int dist = 0;
for (int i = 0; i < word1.length(); i++) {
if (word1.charAt(i) != word2.charAt(i)) {
dist += 1;
}
}
return dist;
}
private static void enQueue(Set<String> dict, LinkedList<String> queue, String target, Map<String, Integer> map, int step) {
if (dict == null || dict.isEmpty()) {
return;
}
for (int i = 0; i < target.length(); i++) {
for (char c = 'a'; c <= 'z'; c++) {
StringBuilder sBuilder = new StringBuilder(target);
if (sBuilder.charAt(i) == c) {
continue;
}
sBuilder.setCharAt(i, c);
if (dict.contains(sBuilder.toString())) {
queue.addLast(sBuilder.toString());
dict.remove(sBuilder.toString());
map.put(sBuilder.toString(), step + 1);
}
}
}
}
private static int bfsDict(Set<String> dict, String start, String end) {
LinkedList<String> queue = new LinkedList<String>();
Map<String, Integer> hashMap = new HashMap<String, Integer>();
enQueue(dict, queue, start, hashMap, 1);
while (!queue.isEmpty()) {
String word = queue.poll();
int step = hashMap.get(word);
if (calDistance(word, end) == 1) {
return step + 1;
}
enQueue(dict, queue, word, hashMap, step);
}
return 0;
}
}