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.
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 class Solution { 2 3 public int ladderLength(String start, String end, Set<String> dict) { 4 if (diff(start, end) == 0) return 1; 5 if (diff(start, end) == 1) return 2; 6 7 ArrayList<String> inner = new ArrayList<String>(); 8 ArrayList<String> outer = new ArrayList<String>(); 9 inner.add(start); 10 int counter = 1; 11 while (inner.size() != 0) { 12 counter++; 13 if (dict.size() == 0) return 0; 14 for (int i = 0; i < inner.size(); i++) { 15 ArrayList<String> dicts = new ArrayList<String>(dict); 16 for (int j = 0; j < dicts.size(); j++) { 17 if (diff(inner.get(i), dicts.get(j)) == 1) { 18 outer.add(dicts.get(j)); 19 dict.remove(dicts.get(j)); 20 } 21 } 22 } 23 24 for (int k = 0; k < outer.size(); k++) { 25 if (diff(outer.get(k), end) <= 1) { 26 return counter + 1; 27 } 28 } 29 30 ArrayList<String> temp = inner; 31 inner = outer; 32 outer = temp; 33 outer.clear(); 34 } 35 return 0; 36 } 37 38 private int diff(String start, String end) { 39 int total = 0; 40 for (int i = 0; i < start.length(); i++) { 41 if (start.charAt(i) != end.charAt(i)) { 42 total++; 43 } 44 } 45 return total; 46 } 47 }
第二种方法:递归,复杂度更高。
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)) { 5 return 0; 6 } 7 Queue<Node> queue = new LinkedList<>(); 8 queue.add(new Node(begin, 1)); 9 10 while (queue.size() != 0) { 11 Node current = queue.poll(); 12 String word = current.word; 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 (set.contains(tempStr)) { 20 if (tempStr.equals(end)) { 21 return current.depth + 1; // we find it 22 } else { 23 set.remove(tempStr); 24 queue.offer(new Node(tempStr, current.depth + 1)); 25 } 26 } 27 } 28 chs[i] = ch; 29 } 30 } 31 return 0; 32 } 33 } 34 35 class Node { 36 String word; 37 int depth; 38 39 public Node(String word, int depth) { 40 this.word = word; 41 this.depth = depth; 42 } 43 }
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 Set<String> dict = new HashSet<>(dictList); 5 Set<String> visited = new HashSet<>(); 6 if (!dict.contains(end)) { 7 return result; 8 } 9 Queue<Node> candidates = new LinkedList<>(); 10 candidates.offer(new Node(start, null)); 11 while (!candidates.isEmpty()) { 12 int count = candidates.size(); 13 for (int k = 1; k <= count; k++) { 14 Node node = candidates.poll(); 15 String word = node.word; 16 if (word.equals(end)) { 17 return result; 18 } 19 20 char[] chs = word.toCharArray(); 21 for (int i = 0; i < chs.length; i++) { 22 char temp = chs[i]; 23 for (char ch = 'a'; ch <= 'z'; ch++) { 24 chs[i] = ch; 25 String newStr = new String(chs); 26 if (dict.contains(newStr)) { 27 visited.add(newStr); 28 Node newNode = new Node(newStr, node); 29 candidates.add(newNode); 30 if (newStr.equals(end)) { 31 addPathToResult(result, newNode) 32 List<String> path = getPath(newNode); 33 result.add(path); 34 } 35 } 36 chs[i] = temp; 37 } 38 } 39 } 40 dict.removeAll(visited); 41 } 42 return result; 43 } 44 45 private List<String> getPath(Node node) { 46 List<String> list = new LinkedList<>(); 47 while (node != null) { 48 list.add(0, node.word); 49 node = node.pre; 50 } 51 return list; 52 } 53 } 54 55 class Node { 56 String word; 57 Node pre; 58 59 public Node(String word, Node pre) { 60 this.word = word; 61 this.pre = pre; 62 } 63 }