標籤:
題目:
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"] ]
思路:先建立dict的鄰接鏈表,例子中的結果如下:
hit : [hot]
cog : [dog, log]
hot : [hit, lot, dot]
lot : [hot, log, dot]
dog : [cog, log, dot]
log : [cog, lot, dog]
dot : [lot, hot, dog]
在Word LadderI的基礎上,由於要重新構建結果集,因此要自己建立一個Node類,儲存每一個節點的上一個節點,這樣在找到最短結果的時候,以此找到該節點的上一個節點,加入鏈表即可。
需要注意的幾點:
(1)構建鄰接鏈表前,需要把start和end加入,這樣才能找到結果。
(2)構建鄰接鏈表的時候,對於每一個單詞,一定要在每一次替換char後,再將其恢複,以便進行下一次判斷。
(3)每一層的queue用一個num來記錄此層的Node個數,只要是找到一個,就證明這一層即為最短路徑,設標誌位為true,將該層迴圈之後,結束迴圈。
(4)迴圈的過程中,需要判斷節點是否已經被判斷過,建立一個Set用於記錄所有判斷過的節點。
代碼:
public class Solution { private class Node{ public Node pre; public String val; public Node(Node p, String s){ pre = p; val = s; } } public List<List<String>> findLadders(String start, String end, Set<String> dict) { dict.add(start); dict.add(end); //注意(1) Map<String, Set<String>> neighbours = calNeighbours(dict); List<List<String>> req = new ArrayList<List<String>>(); LinkedList<Node> queue = new LinkedList<Node>(); queue.offer(new Node(null, start)); //開始節點的前一個為null Set<String> visited = new HashSet<String>(); //注意(4) boolean flag = false; //注意(3) while(!queue.isEmpty() || visited.size() == dict.size()){ int num = queue.size(); for(int i = 0 ; i < num ; i++){ Node n = queue.poll(); if(end.equals(n.val)){ findPath(n, req); flag = true; //注意(3) }else{ Set<String> temp = neighbours.get(n.val); if(temp == null || temp.size() == 0) continue; else{ for(String s : temp){ if(!visited.contains(s)){ //注意(4) queue.offer(new Node(n, s)); } } } } visited.add(n.val);//注意(4) } if(flag) break; } if(!flag) // 如果flag為false,證明無解 return new ArrayList<List<String>>(); return req; } private void findPath(Node n, List<List<String>> req) { // TODO Auto-generated method stub List<String> temp = new ArrayList<String>(); while(n != null){ temp.add(0, n.val); n = n.pre; } req.add(temp); } public Map<String, Set<String>> calNeighbours(Set<String> dict) { Map<String, Set<String>> neighbours = new HashMap<String, Set<String>>(); for(String str : dict){ int len = str.length(); char[] chars = str.toCharArray(); for(int i = 0 ; i < len ; i++){ char old = chars[i]; //注意(2) for(char c = ‘a‘ ; c <= ‘z‘ ; c++){ if(c == chars[i]) continue; chars[i] = c; String newstr = new String(chars); if(dict.contains(newstr)) { Set<String> set = neighbours.get(str); if(set != null) set.add(newstr); else{ Set<String> newset = new HashSet<String>(); newset.add(newstr); neighbours.put(str, newset); } } chars[i] = old ; //注意(2)引用型變數 每一次用完要還原 } // end fot c } // end for len } // end for str return neighbours; }}
AC時間為 1120ms左右,因此還有很大的改進空間,繼續新的思路。
[LeetCode-JAVA] Word Ladder II