原题链接在这里:https://leetcode.com/problems/word-ladder-ii/
它山之石,在生成neighbours时需采用循环,否则会有concurrentModificationException.
可以看看这篇帖子:http://blog.csdn.net/worldwindjp/article/details/19301355
AC Java:
1 public class Solution { 2 public List<List<String>> findLadders(String beginWord, String endWord, Set<String> wordList) { 3 List<List<String>> res = new ArrayList<List<String>>(); 4 HashMap<String, HashSet<String>> neighbours = new HashMap<String, HashSet<String>>(); 5 wordList.add(beginWord); 6 wordList.add(endWord); 7 8 // init adjacent graph 9 //Here is the point of concurrent modification exception 10 for(String str : wordList){ 11 calcNeighbours(neighbours, str, wordList); 12 } 13 14 //BFS 15 LinkedList<Node> que = new LinkedList<Node>(); 16 que.add(new Node(null,beginWord,1)); 17 int preLevel = 0; 18 HashMap<String, Integer> visited = new HashMap<String, Integer>(); 19 20 while(!que.isEmpty()){ 21 Node n = que.poll(); 22 if(n.str.equals(endWord)){ 23 //find one path, check its length, if there is a short one, it means a better one was found before 24 if(preLevel == 0 || n.level == preLevel){ 25 preLevel = n.level; 26 findPath(n,res); 27 }else{ 28 break; 29 } 30 }else{ 31 HashSet<String> curNeighbours = neighbours.get(n.str); 32 if(curNeighbours == null || curNeighbours.isEmpty()){ 33 continue; 34 } 35 36 //concurrent exception 37 List<String> toRemove = new ArrayList<String>(); 38 for(String s : curNeighbours){ 39 if(visited.containsKey(s)){ 40 int preSearchLevel = visited.get(s); 41 if(preSearchLevel<n.level+1){ 42 neighbours.get(s).remove(n.str); 43 toRemove.add(s); 44 continue; 45 } 46 } 47 visited.put(s, n.level+1); 48 que.add(new Node(n,s,n.level+1)); 49 if(neighbours.containsKey(s)){ 50 neighbours.get(s).remove(n.str); 51 } 52 } 53 for(String s : toRemove){ 54 curNeighbours.remove(s); 55 } 56 } 57 } 58 return res; 59 } 60 61 private void calcNeighbours(Map<String, HashSet<String>> neighbours, String str, Set<String> dict) { 62 int length = str.length(); 63 char [] chars = str.toCharArray(); 64 for (int i = 0; i < length; i++) { 65 66 char old = chars[i]; 67 for (char c = 'a'; c <= 'z'; c++) { 68 69 if (c == old) continue; 70 chars[i] = c; 71 String newstr = new String(chars); 72 73 if (dict.contains(newstr)) { 74 HashSet<String> set = neighbours.get(str); 75 if (set != null) { 76 set.add(newstr); 77 } else { 78 HashSet<String> newset = new HashSet<String>(); 79 newset.add(newstr); 80 neighbours.put(str, newset); 81 } 82 } 83 } 84 chars[i] = old; 85 } 86 } 87 88 private void findPath(Node n, List<List<String>> result){ 89 ArrayList<String> path = new ArrayList<String>(); 90 Node p = n; 91 while(p != null){ 92 path.add(0, p.str); 93 p = p.parent; 94 } 95 result.add(path); 96 } 97 } 98 99 class Node{ 100 Node parent; 101 String str; 102 int level; 103 public Node(Node p, String s, int l){ 104 parent = p; 105 str = s; 106 level = l; 107 } 108 }