@Yano
2019-09-20T02:49:08.000000Z
字数 4249
阅读 2101
LeetCode
coding 笔记、点滴记录,以后的文章也会同步到公众号(Coding Insight)中,希望大家关注^_^
https://github.com/LjyYano/Thinking_in_Java_MindMapping

https://leetcode.com/problems/word-ladder/description/
Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence 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"]
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.
Note:
class Solution {public int ladderLength(String beginWord, String endWord, List<String> wordList) {Set<String> set = new HashSet<>(wordList);LinkedList<String> queue = new LinkedList<>();// 在队列中放入初始元素queue.offer(beginWord);int step = 2;while (!queue.isEmpty()) {// 下一步具有的节点数int size = queue.size();while (size > 0) {String currString = queue.poll();Iterator<String> iterator = set.iterator();while (iterator.hasNext()) {String next = iterator.next();int diff = diff(next, currString);// 若当前元素与取出元素差1,并且是endWord,则直接返回结果if (diff == 1 && next.equals(endWord)) {return step;}// 差1就放入队列,并将其删除(此元素可以删除,因为循环读取时长度不是最优解)if (diff == 1) {queue.offer(next);iterator.remove();}}size--;}step++;}return 0;}private int diff(String s1, String s2) {if (s1.length() != s2.length()) {return 0;}int diff = 0;for (int i = 0; i < s1.length(); i++) {if (s1.charAt(i) != s2.charAt(i)) {diff++;}if (diff >= 2) {return 2;}}return diff;}}
https://leetcode.com/problems/word-ladder-ii/description/
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:
部分可以依照上一题,但是这道题是求「所有的最短路径」,而不是「最短路径长度」,单纯的 BFS 无法实现。但是可以使用 BFS 构造数据结构(保证最短路径),并使用 DFS 求路径。
Version 1:没有构造通用的数据结构,map 的 value 记录步骤,在 DFS 时也要重新计算两个字符串差异数。用 set 表示是否 visit 过。
class Solution {public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {// value:从begin到达该key的最短长度。Map<String, Integer> map = new HashMap<>();Set<String> notVisitSet = new HashSet<>(wordList);List<List<String>> ans = new ArrayList<>();if (!notVisitSet.contains(endWord)) {return ans;}// 构建mapbfs(beginWord, endWord, map, notVisitSet);if (map.isEmpty()) {return ans;}map.put(beginWord, 0);// 从end指向begin,否则会超时!因为begin后面可能接多个路径,但是end只有一个dfs(endWord, beginWord, map, ans, new ArrayList<>(Arrays.asList(endWord)));return ans;}private void bfs(String beginWord, String endWord, Map<String, Integer> map, Set<String> notVisitSet) {LinkedList<String> queue = new LinkedList<>();// 在队列中放入初始元素queue.offer(beginWord);boolean find = false;int level = 1;while (!queue.isEmpty()) {int size = queue.size();while (size > 0) {String curr = queue.poll();Iterator<String> iterator = notVisitSet.iterator();while (iterator.hasNext()) {String next = iterator.next();int diff = diff(curr, next);if (diff == 1) {// 若在某一步找到,则当前步数结束即可if (next.equals(endWord)) {find = true;}queue.offer(next);iterator.remove();map.put(next, level);}}size--;}if (find) {break;}level++;}}private void dfs(String beginWord, String endWord, Map<String, Integer> map, List<List<String>> ans,List<String> tmp) {if (beginWord.equals(endWord)) {List<String> arrayList = new ArrayList<>(tmp);Collections.reverse(arrayList);ans.add(arrayList);return;}for (String key : map.keySet()) {// 要判断 diff,因为本层和下一层没有必然联系if (map.get(key) == map.get(beginWord) - 1 && diff(beginWord, key) == 1) {tmp.add(key);dfs(key, endWord, map, ans, tmp);tmp.remove(tmp.size() - 1);}}}private int diff(String s1, String s2) {if (s1.length() != s2.length()) {return 0;}int diff = 0;for (int i = 0; i < s1.length(); i++) {if (s1.charAt(i) != s2.charAt(i)) {diff++;}if (diff >= 2) {return 2;}}return diff;}}