2020-03-19 13:10:35
问题描述:
给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:
- 每次转换只能改变一个字母。
- 转换过程中的中间单词必须是字典中的单词。
说明:
- 如果不存在这样的转换序列,返回一个空列表。
- 所有单词具有相同的长度。
- 所有单词只由小写字母组成。
- 字典中不存在重复的单词。
- 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例 1:
输入: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"] 输出: [ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ]
示例 2:
输入: beginWord = "hit" endWord = "cog" wordList = ["hot","dot","dog","lot","log"] 输出: [] 解释: endWord "cog" 不在字典中,所以不存在符合要求的转换序列。
问题求解:
总体思路是先通过BFS搜索最小步数,并且记录BFS树,之后使用DFS得到路径。这里有个地方需要特别注意的是,在构建BFS树的时候,需要在某一层全部遍历结束后再把下一层的一起加入used中,否则会少掉一些上层到下层的边。
时间复杂度:O(n)
List<List<String>> res = new ArrayList<>(); Set<String> dict = new HashSet<>(); Map<String, Set<String>> graph = new HashMap<>(); public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) { for (String s : wordList) dict.add(s); if (!dict.contains(endWord)) return res; int step = bfs(beginWord, endWord); if (step == -1) return res; dfs(beginWord, endWord, new ArrayList<>(), step + 1); return res; } private void dfs(String begin, String end, List<String> curr, int step) { curr.add(begin); if (curr.size() == step) { if (curr.get(step - 1).equals(end)) res.add(new ArrayList<>(curr)); } else { for (String next : graph.get(begin)) { dfs(next, end, curr, step); } } curr.remove(curr.size() - 1); } private int bfs(String begin, String end) { boolean flag = false; Queue<String> q = new LinkedList<>(); Set<String> used = new HashSet<>(); q.add(begin); used.add(begin); int step = 0; while (!q.isEmpty()) { if (flag) return step; int size = q.size(); Set<String> layer_used = new HashSet<>(); for (int k = 0; k < size; k++) { String curr = q.poll(); if (!graph.containsKey(curr)) graph.put(curr, new HashSet<>()); char[] chs = curr.toCharArray(); for (int i = 0; i < chs.length; i++) { char ch = chs[i]; for (char c = 'a'; c <= 'z'; c++) { if (c == ch) continue; chs[i] = c; String next = new String(chs); if (next.equals(end)) flag = true; if (!dict.contains(next) || used.contains(next)) continue; graph.get(curr).add(next); q.add(next); layer_used.add(next); } chs[i] = ch; } } step += 1; used.addAll(layer_used); } return -1; }