126. Word Ladder II Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that: 1. Only one letter can be changed at a time 2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word. Note: * Return an empty list if there is no such transformation sequence. * All words have the same length. * All words contain only lowercase alphabetic characters. * You may assume no duplicates in the word list. * You may assume beginWord and endWord are non-empty and are not the same. Example 1: Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"] Output: [ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ] Example 2: Input: beginWord = "hit" endWord = "cog" wordList = ["hot","dot","dog","lot","log"] Output: [] Explanation: The endWord "cog" is not in wordList, therefore no possible transformation. // need to debug this Your input "hit" "cog" ["hot","dot","dog","lot","log","cog"] Your answer [] Expected answer [["hit","hot","lot","log","cog"],["hit","hot","dot","dog","cog"]] // my code, not passed class Solution { public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) { // use bfs to find the shortest path and use map tpo store parent child relations // use dfs to get all the paths Set<String> dict = new HashSet<>(); for(String word : dict) dict.add(word); Map<String, List<String>> map = new HashMap<>(); for(String word : dict) map.put(word, new ArrayList<>()); Map<String, Integer> distance = new HashMap<>(); List<List<String>> res = new ArrayList<>(); List<String> path = new ArrayList<>(); bfs(beginWord, endWord, map, distance, dict); path.add(endWord); dfs(res, path, beginWord, endWord, distance, map); return res; } private void bfs(String beginWord, String endWord, Map<String, List<String>> map, Map<String, Integer> distance, Set<String> dict){ Queue<String> queue = new LinkedList<>(); int level = 1; boolean found = false; queue.offer(beginWord); while(!queue.isEmpty()){ int size = queue.size(); for(int i = 0; i < size; i++){ String curWord = queue.poll(); List<String> neis = getNei(dict, curWord); // if it's the first time visiting this nei, then add it in distance map // else , don't update, since this is not the shortest distance from this nei to beginWord for(String nei : neis){ if(!distance.containsKey(nei)){ distance.put(nei, level); } map.get(nei).add(curWord); if(nei.equals(endWord)) found = true; } } if(found) break; level++; } } private List<String> getNei(Set<String> dict, String curWord){ List<String> res = new ArrayList<>(); char[] curArray = curWord.toCharArray(); for(int i = 0; i < curArray.length; i++){ char c = curArray[i]; for(char ch = 'a'; ch <= 'z'; ch++){ curArray[i] = ch; if(ch == c) continue; curArray[i] = c; String newWord = new String(curArray); if(dict.contains(newWord)) res.add(newWord); } } return res; } private void dfs(List<List<String>> res, List<String> path, String beginWord, String endWord, Map<String, Integer> distance, Map<String, List<String>> map){ // base case if(beginWord.equals(endWord)){ Collections.reverse(path); res.add(path); } if(map.get(endWord) != null && map.get(endWord).size() != 0){ for(String word : map.get(endWord)){ // only add the word, whose distance is endWord's distance - 1 if(distance.get(endWord) == distance.get(word) + 1){ path.add(word); dfs(res, path, beginWord, word, distance, map); // backtracking path.remove(path.size() - 1); } } } } } // other’s code, accepted class Solution { public List<List<String>> findLadders(String start, String end, List<String> wordList) { HashSet<String> dict = new HashSet<String>(wordList); List<List<String>> res = new ArrayList<>(); Map<String, List<String>> nodeNeis = new HashMap<>(); HashMap<String, Integer> distance = new HashMap<>(); List<String> solution = new ArrayList<>(); dict.add(start); bfs(start, end, dict, nodeNeis, distance); solution.add(start); dfs(start, end, dict, nodeNeis, distance, solution, res); return res; } private void bfs(String start, String end, Set<String> dict, Map<String, List<String>> nodeNeis, Map<String, Integer> distance){ for(String str : dict) nodeNeis.put(str, new ArrayList<>()); Queue<String> queue = new LinkedList<>(); queue.offer(start); distance.put(start, 0); while(!queue.isEmpty()){ int size = queue.size(); boolean foundEnd = false; for(int i = 0; i < size; i++){ String cur = queue.poll(); int curDistance = distance.get(cur); List<String> neis = getNeis(cur, dict); for(String nei : neis){ nodeNeis.get(cur).add(nei); if(!distance.containsKey(nei)){ distance.put(nei, curDistance + 1); if(end.equals(nei)){ foundEnd = true; }else{ queue.offer(nei); } } } if(foundEnd){ break; } } } } private List<String> getNeis(String node, Set<String> dict){ List<String> res = new ArrayList<>(); char[] curArray = node.toCharArray(); for(int i = 0; i < curArray.length; i++){ char c = curArray[i]; for(char ch = 'a'; ch <= 'z'; ch++){ if(ch == c) continue; curArray[i] = ch; String curWord = new String(curArray); if(dict.contains(curWord)) res.add(curWord); } curArray[i] = c; } return res; } private void dfs(String cur, String end, Set<String> dict, Map<String, List<String>> nodeNeis, Map<String, Integer> distance, List<String> solution, List<List<String>> res){ if(end.equals(cur)){ res.add(new ArrayList<>(solution)); }else{ for(String next : nodeNeis.get(cur)){ if(distance.get(next) == distance.get(cur) + 1){ solution.add(next); dfs(next, end, dict, nodeNeis, distance, solution, res); solution.remove(solution.size() - 1); } } } } } // Input: // beginWord = "hit", // endWord = "cog", // wordList = ["hot","dot","dog","lot","log","cog"] // Output: // [ // ["hit","hot","dot","dog","cog"], // ["hit","hot","lot","log","cog"] // ] // map : cog // dog, log // distance :