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"] ]
Leetcode 里面通过概率最低的一道题,参看了别人的解法:利用bfs 层序遍历 如果队列中有end 那么结束遍历(到最短的一层就结束)
1 import java.util.ArrayList; 2 import java.util.HashMap; 3 import java.util.HashSet; 4 import java.util.LinkedList; 5 import java.util.List; 6 import java.util.Map; 7 import java.util.Queue; 8 import java.util.Set; 9 10 public class Solution { 11 class WordWithLevel { 12 String word; 13 int level; 14 15 public WordWithLevel(String word, int level) { 16 this.word = word; 17 this.level = level; 18 } 19 } 20 21 private String end; 22 private ArrayList<ArrayList<String>> result; 23 private Map<String, List<String>> nextMap; 24 25 public ArrayList<ArrayList<String>> findLadders(String start, String end, 26 HashSet<String> dict) { 27 result = new ArrayList<ArrayList<String>>(); 28 this.end = end; 29 30 // unvisited words set 31 Set<String> unVisited = new HashSet<String>(); 32 unVisited.addAll(dict); 33 unVisited.add(start); 34 unVisited.remove(end); 35 36 // used to record the map info of <word : the words of next level> 37 nextMap = new HashMap<String, List<String>>(); 38 for (String e : unVisited) { 39 nextMap.put(e, new ArrayList<String>()); 40 } 41 42 // BFS to search from the end to start 43 Queue<WordWithLevel> queue = new LinkedList<WordWithLevel>(); 44 queue.add(new WordWithLevel(end, 0)); 45 boolean found = false; 46 int finalLevel = Integer.MAX_VALUE; 47 int currentLevel = 0; 48 int preLevel = 0; 49 Set<String> visitedWordsInThisLevel = new HashSet<String>(); 50 while (!queue.isEmpty()) { 51 WordWithLevel wordWithLevel = queue.poll(); 52 String word = wordWithLevel.word; 53 currentLevel = wordWithLevel.level; 54 if (found && currentLevel > finalLevel) { 55 break; 56 } 57 if (currentLevel > preLevel) { 58 unVisited.removeAll(visitedWordsInThisLevel); 59 } 60 preLevel = currentLevel; 61 char[] wordCharArray = word.toCharArray(); 62 for (int i = 0; i < word.length(); ++i) { 63 char originalChar = wordCharArray[i]; 64 boolean foundInThisCycle = false; 65 for (char c = 'a'; c <= 'z'; ++c) { 66 wordCharArray[i] = c; 67 String newWord = new String(wordCharArray); 68 if (c != originalChar && unVisited.contains(newWord)) { 69 nextMap.get(newWord).add(word); 70 if (newWord.equals(start)) { 71 found = true; 72 finalLevel = currentLevel; 73 foundInThisCycle = true; 74 break; 75 } 76 if (visitedWordsInThisLevel.add(newWord)) { 77 queue.add(new WordWithLevel(newWord, 78 currentLevel + 1)); 79 } 80 } 81 } 82 if (foundInThisCycle) { 83 break; 84 } 85 wordCharArray[i] = originalChar; 86 } 87 } 88 89 if (found) { 90 // dfs to get the paths 91 ArrayList<String> list = new ArrayList<String>(); 92 list.add(start); 93 getPaths(start, list, finalLevel + 1); 94 } 95 return result; 96 } 97 98 private void getPaths(String currentWord, ArrayList<String> list, int level) { 99 if (currentWord.equals(end)) { 100 result.add(new ArrayList<String>(list)); 101 } else if (level > 0) { 102 List<String> parentsSet = nextMap.get(currentWord); 103 for (String parent : parentsSet) { 104 list.add(parent); 105 getPaths(parent, list, level - 1); 106 list.remove(list.size() - 1); 107 } 108 } 109 } 110 }
自己的解法还需要多想想:
1 public class Solution { 2 public ArrayList<ArrayList<String>> findLadders(String start, String end, Set<String> dict) { 3 ArrayList<String> Ladder=new ArrayList<String>(); 4 ArrayList<ArrayList<String>> LadderList=new ArrayList<ArrayList<String>>(); 5 if(start.length() != end.length()) return LadderList; 6 shortestladders(start, end, dict, Ladder, LadderList); 7 return LadderList; 8 } 9 10 public void shortestladders(String start, String end, Set<String> dict, ArrayList<String> Ladder, ArrayList<ArrayList<String>> LadderList){ 11 Ladder.add(start); 12 if(within(start, end)) { //end is only 1 bit different from start 13 Ladder.add(end); 14 if(LadderList.isEmpty()) { //LadderList is empty, so Ladder is definately shortest 15 LadderList.add(Ladder); 16 } 17 else { //LadderList is not empty, so need comparition 18 ArrayList<String> shortestLadder = LadderList.get(0); // select one from LadderList 19 if(Ladder.size() < shortestLadder.size()) { //new found Ladder is shorter than LadderList 20 LadderList.clear(); 21 LadderList.add(Ladder); 22 } 23 else if(Ladder.size() == shortestLadder.size()) { //new found Ladder is the same with the LadderList,add to Ladderlist 24 LadderList.add(Ladder); 25 } 26 // new found Ladder is longer than elems in LadderList, so do not change LadderList 27 } 28 Ladder.remove(Ladder.size()-1); //remove end 29 } 30 31 else { //end is more than 1 bit different from start, so look for temp elems in dict which is 1 bit different from start 32 if(!dict.isEmpty()) { 33 for(String temp:dict){ 34 if(within(start, temp)){ 35 dict.remove(start); 36 shortestladders(temp, end, dict, Ladder, LadderList); 37 dict.add(start); 38 } 39 } 40 } 41 42 } 43 Ladder.remove(Ladder.size()-1); //remove start 44 } 45 46 public boolean within(String first, String second){ 47 int diff=0; 48 for(int k=0; k<first.length(); k++){ 49 if(first.charAt(k)!=second.charAt(k)){ 50 diff++; 51 } 52 } 53 if(diff==1) return true; 54 else return false; 55 } 56 }