Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:
- Only one letter can be changed at a time
- Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
Return
[ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ]
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.
package leetCode; import java.util.*; /** * Created by lxw, liwei4939@126.com on 2018/3/26. */ public class L126_WordLadder { public List<List<String>> findLadders(String start, String end, List<String> wordList){ HashSet<String> dict = new HashSet<>(wordList); List<List<String>> res= new ArrayList<>(); HashMap<String, ArrayList<String>> nodeNeighbors = new HashMap<>(); HashMap<String, Integer> distance = new HashMap<>(); ArrayList<String> solution = new ArrayList<>(); dict.add(start); bfs(start, end, dict, nodeNeighbors, distance); dfs(start, end, dict, nodeNeighbors, distance, solution,res); return res; } private void bfs(String start, String end, HashSet<String> dict, HashMap<String, ArrayList<String>> nodeNeighbors, HashMap<String, Integer> distance){ for (String str : dict){ nodeNeighbors.put(str, new ArrayList<String>()); } Queue<String> queue = new LinkedList<>(); queue.offer(start); distance.put(start, 0); while (!queue.isEmpty()){ int count = queue.size(); boolean foundEnd = false; for (int i =0; i < count; i++){ String cur = queue.poll(); int curDistance = distance.get(cur); ArrayList<String> neighbors = getNeighbors(cur, dict); for (String neighbor : neighbors){ nodeNeighbors.get(cur).add(neighbor); if (!distance.containsKey(neighbor)){ distance.put(neighbor, curDistance+1); if (end.equals(neighbor)){ foundEnd = true; } else { queue.offer(neighbor); } } } } if (foundEnd){ break; } } } private void dfs(String cur, String end, HashSet<String> dict, HashMap<String, ArrayList<String>> nodeNeighbors, HashMap<String, Integer> distance, ArrayList<String> solution, List<List<String>> res){ solution.add(cur); if (cur.equals(end)){ res.add(new ArrayList<String>(solution)); } else { for (String next : nodeNeighbors.get(cur)){ if (distance.get(next) == distance.get(cur) + 1){ dfs(next, end, dict, nodeNeighbors, distance, solution, res); } } } solution.remove(solution.size() - 1); } private ArrayList<String> getNeighbors(String str, HashSet<String> dict){ ArrayList<String> res = new ArrayList<>(); if (str == null || dict == null){ return res; } for (int i = 0; i < str.length(); i++){ StringBuilder builder = new StringBuilder(str); for (char ch = 'a'; ch <= 'z'; ch++){ builder.setCharAt(i, ch); String new_str = builder.toString(); if (dict.contains(new_str)){ res.add(new_str); } } } return res; } }