126. Word Ladder I & II
Word Ladder I
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
Notice
- Return 0 if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
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
.
分析:
BFS。
1 public int ladderLength(String begin, String end, List<String> list) { 2 Set<String> visited = new HashSet<>(); 3 if (!list.contains(end)) return 0; 4 Queue<String> queue = new LinkedList<>(); 5 int level = 1; 6 queue.add(begin); 7 visited.add(begin); 8 while (!queue.isEmpty()) { 9 level++; 10 int size = queue.size(); 11 for (int k = 1; k <= size; k++) { 12 String word = queue.poll(); 13 for (String neighbor : getNeighbors(word, new HashSet<>(list))) { 14 if (neighbor.equals(end)) return level; 15 if (!visited.contains(neighbor)) { 16 visited.add(neighbor); 17 queue.offer(neighbor); 18 } 19 } 20 } 21 } 22 return 0; 23 } 24 25 private List<String> getNeighbors(String word, Set<String> set) { 26 List<String> neighbors = new ArrayList<>(); 27 char[] chs = word.toCharArray(); 28 for (int i = 0; i < chs.length; i++) { 29 char ch = chs[i]; 30 for (char temp = 'a'; temp <= 'z'; temp++) { 31 chs[i] = temp; 32 String neighbor = new String(chs); 33 if (set.contains(neighbor) && !word.equals(neighbor)) { 34 neighbors.add(neighbor); 35 } 36 } 37 chs[i] = ch; 38 } 39 return neighbors; 40 }
第二种方法:递归,复杂度更高。
1 public class Solution { 2 public static void main(String[] args) { 3 Set<String> set = new HashSet<String>(); 4 set.add("hot"); 5 set.add("dot"); 6 set.add("dog"); 7 set.add("lot"); 8 set.add("log"); 9 10 Solution s = new Solution(); 11 System.out.println(s.ladderLength("hit", "cog", set)); 12 } 13 14 public List<List<String>> ladderLength(String begin, String end, Set<String> set) { 15 16 List<String> list = new ArrayList<String>(); 17 List<List<String>> listAll = new ArrayList<List<String>>(); 18 Set<String> used = new HashSet<String>(); 19 helper(begin, end, list, listAll, used, set); 20 return listAll; 21 } 22 23 // find out all possible solutions 24 public void helper(String current, String end, List<String> list, List<List<String>> listAll, Set<String> used, 25 Set<String> set) { 26 list.add(current); 27 used.add(current); 28 29 if (diff(current, end) == 1) { 30 ArrayList<String> temp = new ArrayList<String>(list); 31 temp.add(end); 32 listAll.add(temp); 33 } 34 35 for (String str : set) { 36 if (!used.contains(str) && diff(current, str) == 1) { 37 helper(str, end, list, listAll, used, set); 38 } 39 } 40 list.remove(current); 41 used.remove(current); 42 } 43 44 // return the # of letters difference 45 public int diff(String word1, String word2) { 46 47 int count = 0; 48 for (int i = 0; i < word1.length(); i++) { 49 if (word1.charAt(i) != word2.charAt(i)) { 50 count++; 51 } 52 } 53 return count; 54 } 55 }
方法3
1 class Solution { 2 public int ladderLength(String begin, String end, List<String> list) { 3 Set<String> set = new HashSet<>(list); 4 if (!set.contains(end)) return 0; 5 Queue<String> queue = new LinkedList<>(); 6 int level = 0; 7 queue.add(begin); 8 while (queue.size() != 0) { 9 level++; 10 int size = queue.size(); 11 for (int k = 1; k <= size; k++) { 12 String word = queue.poll(); 13 char[] chs = word.toCharArray(); 14 for (int i = 0; i < chs.length; i++) { 15 char ch = chs[i]; 16 for (char temp = 'a'; temp <= 'z'; temp++) { 17 chs[i] = temp; 18 String tempStr = new String(chs); 19 if (tempStr.equals(end)) return level + 1; 20 if (set.contains(tempStr)) { 21 set.remove(tempStr); 22 queue.offer(tempStr); 23 } 24 } 25 chs[i] = ch; 26 } 27 } 28 } 29 return 0; 30 } 31 }
Word Ladder II
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that: 1) Only one letter can be changed at a time, 2) Each intermediate word must exist in the dictionary.
For example, given: start = "hit", end = "cog", and dict = ["hot","dot","dog","lot","log"], return:
[ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ]
分析:
原理同上,按照层进行递进,当最外层到达end以后,我们就退出。
1 class Solution { 2 public List<List<String>> findLadders(String start, String end, List<String> dictList) { 3 List<List<String>> result = new ArrayList<>(); 4 boolean hasFound = false; 5 Set<String> dict = new HashSet<>(dictList); 6 Set<String> visited = new HashSet<>(); 7 if (!dict.contains(end)) { 8 return result; 9 } 10 Queue<Node> candidates = new LinkedList<>(); 11 candidates.offer(new Node(start, null)); 12 while (!candidates.isEmpty()) { 13 int count = candidates.size(); 14 if (hasFound) return result; 15 for (int k = 1; k <= count; k++) { 16 Node node = candidates.poll(); 17 String word = node.word; 18 char[] chs = word.toCharArray(); 19 for (int i = 0; i < chs.length; i++) { 20 char temp = chs[i]; 21 for (char ch = 'a'; ch <= 'z'; ch++) { 22 chs[i] = ch; 23 String newStr = new String(chs); 24 if (dict.contains(newStr)) { 25 visited.add(newStr); 26 Node newNode = new Node(newStr, node); 27 candidates.add(newNode); 28 if (newStr.equals(end)) { 29 hasFound = true; 30 List<String> path = getPath(newNode); 31 result.add(path); 32 } 33 } 34 } 35 chs[i] = temp; 36 } 37 } 38 dict.removeAll(visited); 39 } 40 return result; 41 } 42 43 private List<String> getPath(Node node) { 44 List<String> list = new LinkedList<>(); 45 while (node != null) { 46 list.add(0, node.word); 47 node = node.pre; 48 } 49 return list; 50 } 51 } 52 53 class Node { 54 String word; 55 Node pre; 56 57 public Node(String word, Node pre) { 58 this.word = word; 59 this.pre = pre; 60 } 61 }