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.
其實這題可以看成是一個圖論裏的最短路徑問題:把每一個字典裏的詞都看成一個節點,如果兩個詞之間能夠只通過修改一個字母即可相等,那麼就可以認爲兩個節點相連,而且距離爲1。因此,這題可以看做是求一條從start到end的最短路徑。注意這裏從start到自身的距離應該爲1,而不能是0。
這題不能用DP做,因爲DP本質是用空間換時間,而這裏需要緩存的中間狀態實在太多,隨着路徑長度指數級增長,內存根本不夠用。所以這題只要在最基本的BFS和DFS裏挑一個就行了。由於這裏不是要求所有的路徑而是求的最短路徑,故應該使用BFS而非DFS。
確定好思路後,可以將BFS所有已經探索到的節點都放到一個HashMap裏,key存節點值,即string值,value存距離值。
由於我這裏用的Java實現,String類裏面沒有類似C++裏的replace方法,所以自己實現了一個replace方法作爲輔助。
public int ladderLength(String start, String end,
HashSet<String> dict) {
Map<String, Integer> map = new HashMap<String, Integer>();
Queue<String> queue = new LinkedList<String>();
queue.offer(start);
map.put(start, 1);
while (!queue.isEmpty()) {
String str = queue.poll();
int dist = map.get(str);
if (str.equals(end))
return dist;
for (int i = 0; i < str.length(); i++) {
for (int j = 0; j <= 25; j++) {
// transform it into another word
String newStr = replace(str, i, (char) ('a' + j));
// if a new word is explored
if (!map.containsKey(newStr) && dict.contains(newStr)) {
map.put(newStr, dist + 1);
queue.offer(newStr);
}
}
}
}
return 0;
}
// replace the index of the given string with the given char
private String replace(String str, int index, char c) {
StringBuilder sb = new StringBuilder(str);
sb.setCharAt(index, c);
return sb.toString();
}