題目描述
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) 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"]
Return:
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Note:
All words have the same length.
All words contain only lowercase alphabetic characters.
思路:
與上一題不同,這次需要存儲所有的最短路徑,就不能在入隊前把字典中的節(jié)點除去还最。我們需要一個隊列存儲路徑,每次取出隊列頭的路徑死遭,把隊頭路徑的最后一個節(jié)點拿出來尋找下一個可達的節(jié)點并存入set中圣猎,如果可達節(jié)點為end節(jié)點,則將路徑保存進結(jié)果列表中狸页,如果不為end節(jié)點落恼,則生成新的路徑存入隊尾箩退。如果路徑長度大于當前路徑長度(也就是層數(shù)),則更新當前路徑長度佳谦,同時將set中節(jié)點都從字典中清除戴涝,因為這些節(jié)點都是上層的節(jié)點,我們不希望再走回頭路,這肯定不是最短路徑了喊括。如果發(fā)現(xiàn)當前路徑長度已經(jīng)大于到達end節(jié)點的路徑長度了胧瓜,則后面的路徑都不是最短路徑了,直接break郑什。
代碼:
import java.util.*;
public class Solution {
public ArrayList<ArrayList<String>> findLadders(String start, String end, HashSet<String> dict) {
ArrayList<ArrayList<String>> res = new ArrayList();
Queue<ArrayList<String>> paths = new LinkedList();
ArrayList<String> startPath = new ArrayList();
startPath.add(start);
paths.offer(startPath);
HashSet<String> nodeToMove = new HashSet();
int level = 1, lastLevel = Integer.MAX_VALUE;
while (!paths.isEmpty()){
ArrayList<String> path = paths.poll();
// 如果當前頭部的路徑長度已經(jīng)超過level府喳,說明已經(jīng)到了下一層,之前的節(jié)點都可以清除了
if (path.size() > level){
// 從字典中清除節(jié)點
dict.removeAll(nodeToMove);
// 清除記錄的節(jié)點
nodeToMove.clear();
// 更新路徑長度
level = path.size();
// 如果長度大于到達終點的最短路徑蘑拯,則退出循環(huán)
if (level > lastLevel) break;
}
// 拿到頭部路徑的最后一個節(jié)點
String last = path.get(path.size() - 1);
char str[] = last.toCharArray();
// 尋找下一個節(jié)點
for (int i=0; i<str.length; i++){
char original = str[i];
for (char c='a'; c<='z'; c++){
str[i] = c;
String next = new String(str);
// 如果節(jié)點在字典中存在
if (dict.contains(next)){
// 記錄要清除的節(jié)點
nodeToMove.add(next);
// 創(chuàng)建新的路徑并把下一個節(jié)點加入
ArrayList<String> nextPath = new ArrayList(path);
nextPath.add(next);
// 如果已經(jīng)到達終點則加入結(jié)果的列表中钝满,并記錄最短路徑長度
if (next.equals(end)){
res.add(nextPath);
lastLevel = level;
}
// 否則將路徑加入隊列的隊尾
else {
paths.offer(nextPath);
}
}
str[i] = original;
}
}
}
return res;
}
}