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
Notice
- All words have the same length.
- All words contain only lowercase alphabetic characters.
Example
Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
Return
[ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ]
算法:BFS+DFS。
先BFS一次,从终点往回层级遍历,记录dict一部分单词到终点的距离Map<String, Integer> map。
再DFS一次,每次尝试加新节点,要求 1.新节点在map里,说明节点是dict里可能出现在最短路径上的那一部分单词。2.map.get(新节点) < map.get(上一节点)说明你这一步能让你离终点更近,不是鸡肋步。一直加到加入了end点那就结束了。
public class Solution { /* * @param start: a string * @param end: a string * @param dict: a set of string * @return: a list of lists of string */ public List<List<String>> findLadders(String start, String end, Set<String> dict) { // write your code here List<List<String>> result = new ArrayList<>(); List<String> list = new ArrayList<String>(); list.add(start); if (start.equals(end)) { // 切记arraylist的构造器deepcopy方法不是把元素传进去,是把同等级的含有元素的collection传进去 //result.add(new ArrayList<String>(start)); result.add(list); return result; } if (dict == null) { return result; } Map<String, Integer> remDist = bfs(start, end, dict); dfs(start, end, remDist, list, result); return result; } private void dfs(String start, String end, Map<String, Integer> remDist, List<String> crt, List<List<String>> result) { // 应该可以去掉一个记录crt里面有什么字符串的set参数吧?因为remDist默默起了相似的帮助去重的作用 if (start.equals(end)) { result.add(new ArrayList<String>(crt)); } for (int idx = 0; idx < start.length(); idx++) { for (char c = 'a'; c <= 'z'; c++) { String newStr = changeChar(start, idx, c); if (!remDist.containsKey(newStr) || remDist.get(newStr) >= remDist.get(start)) { continue; } crt.add(newStr); dfs(newStr, end, remDist, crt, result); crt.remove(crt.size() - 1); } } } private Map<String, Integer> bfs(String start, String end, Set<String> dict) { Map<String, Integer> map = new HashMap<>(); Queue<String> queue = new LinkedList<>(); Set<String> set = new HashSet<>(); int step = 0; queue.offer(end); set.add(end); while (!queue.isEmpty()) { int size = queue.size(); for (int i = 0; i < size; i++) { String crt = queue.poll(); map.put(crt, step); if (crt.equals(start)) { return map; } for (int idx = 0; idx < crt.length(); idx++) { for (char c = 'a'; c <= 'z'; c++) { String newStr = changeChar(crt, idx, c); if (!dict.contains(newStr) && !newStr.equals(start)) { continue; } if (!set.contains(newStr)) { queue.offer(newStr); set.add(newStr); } } } } step++; } return map; } private String changeChar(String crt, int idx, char c) { char[] chars = crt.toCharArray(); chars[idx] = c; return new String(chars); } }