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
For example, Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
Return
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Note:
- All words have the same length.
- All words contain only lowercase alphabetic characters.
Solution 1:
public List<List<String>> findLadders(String start, String end, Set<String> dict) { List<List<String>> result = new ArrayList<>(); if(start == null || end == null || start.length()!=end.length()) return result; int minLen = Integer.MAX_VALUE; // shortest transform sequence length Map<String, Set<String>> visited = new HashMap<>(); // <nextword, previous_words> Map<String, Integer> level = new HashMap<>(); // <nextword, level> Queue<String> queue = new LinkedList<>(); // BFS next word queue visited.put(start, new HashSet<>()); // start word has no previous words level.put(start, 1); queue.offer(start); while (!queue.isEmpty()) { String word = queue.poll(); int preLevel = level.get(word); if (preLevel >= minLen) continue; char[] chars = word.toCharArray(); for (int i = 0; i < word.length(); i++) { char old = chars[i]; for (char letter = 'a'; letter <= 'z'; letter++) { if(letter == old) continue; chars[i] = letter; String nextWord = new String(chars); if(!dict.contains(nextWord)) continue; // if level doesn't contain next word if(!level.containsKey(nextWord)) { Set<String> preWords = new HashSet<>(); preWords.add(word); visited.put(nextWord, preWords); level.put(nextWord, preLevel + 1); queue.add(nextWord); // if level contains next word and near the start } else if(level.get(nextWord) > preLevel) { visited.get(nextWord).add(word); } if (nextWord.equals(end)) { minLen = preLevel + 1; } } chars[i] = old; } } buildPaths(end, visited, new LinkedList<>(), result); return result; } private void buildPaths(String end, Map<String, Set<String>> visited, List<String> path, List<List<String>> paths) { path.add(0, end); Set<String> preWords = visited.get(end); if(preWords == null) return; // can't transform from start to end if (preWords.size() == 0) { // reached start word paths.add(new ArrayList<String>(path)); } else { for (String pre : preWords) { buildPaths(pre, visited, path, paths); } } path.remove(0); }
Solution 2:
private class Node { String word; int depth; public Node(String w, int d) { word = w; depth = d; } } public List<List<String>> findLadders(String start, String end, Set<String> dict) { List<List<String>> paths = new ArrayList<List<String>>(); if (start == null || end == null || start.length() == 0) return paths; // maintain a hashmap for visited words Map<String, List<Node>> visited = new HashMap<String, List<Node>>(); // BFS to find the minimum sequence length getMinLength(start, end, dict, visited); // DFS to back trace paths from end to start buildPaths(end, start, visited, new LinkedList<String>(), paths); return paths; } /** * Use BFS to find the minimum transformation sequences length from start to * end. Also store parent nodes from previous level for each visited valid word. */ private void getMinLength(String start, String end, Set<String> dict, Map<String, List<Node>> visited) { // maintain a queue for words, depth and previous word during BSF Queue<Node> queue = new LinkedList<Node>(); queue.add(new Node(start, 1)); dict.add(end); int lastLevel = 0; while (!queue.isEmpty()) { Node node = queue.poll(); if (lastLevel > 0 && node.depth >= lastLevel) break; // find transformable words in next level for (int i = 0; i < node.word.length(); ++i) { StringBuilder sb = new StringBuilder(node.word); char original = sb.charAt(i); for (char c = 'a'; c <= 'z'; ++c) { if (c == original) continue; sb.setCharAt(i, c); String s = sb.toString(); // if hits end, mark the current depth as the last level if (s.equals(end) && lastLevel == 0) { lastLevel = node.depth + 1; } if (dict.contains(s) && !s.equals(start)) { List<Node> pres = visited.get(s); if (pres == null) { // enqueue unvisited word queue.add(new Node(s, node.depth + 1)); pres = new ArrayList<Node>(); visited.put(s, pres); pres.add(node); } else if (pres.get(0).depth == node.depth) { // parent nodes should be in the same level - to // avoid circle in graph pres.add(node); } } } } } } /* Use DFS to back trace all paths from end to start. */ private void buildPaths(String s, String start, Map<String, List<Node>> visited, List<String> path, List<List<String>> paths) { path.add(0, s); if (s.equals(start)) { List<String> p = new ArrayList<String>(path); paths.add(p); } else { List<Node> pres = visited.get(s); if (pres != null) { for (Node pre : pres) { buildPaths(pre.word, start, visited, path, paths); } } } path.remove(0); }
Reference:
http://n00tc0d3r.blogspot.com/2013/07/word-ladder-ii.html
http://decomplexify.blogspot.com/2014/05/word-ladder-ii.html
相关推荐
javascript js_leetcode题解之126-word-ladder-ii.js
python python_leetcode题解之126_Word_Ladder_II
1. leetCode-126-Word-LadderII.md:这涉及到第126题,词梯问题,通常是一个字符串转换问题,目标是找到两个单词之间的最短转换序列,每次只改变一个字母。 2. leetcode-224-Basic-Calculator.md:这是第224题,基础...
javascript js_leetcode题解之127-word-ladder.js
《LeetCode---C++实现》是一本专注于C++编程语言解决LeetCode在线判题平台上的算法问题的书籍。LeetCode是程序员广泛使用的平台,它提供了大量的编程题目来提升编程技能和算法理解,尤其对于准备面试的程序员来说,...
leetcode-cli-plugins leetcode-cli 的第 3 方插件。 什么是 如何使用 如何使用 插件 名称 描述 增强的命令 按公司或标签过滤问题 list 不要在同一台计算机上使 Chrome 的会话过期 login 不要在同一台计算机上使 ...
javascript js_leetcode题解之140-word-break-ii.js
哈希表 - LeetCode刷题 - 题解
python python_leetcode题解之127_Word_Ladder
java java_leetcode-113-path-sumII
LeetCode 101 - A Grinding Guide.pdf
leetcode-cli 一个享受 leetcode 的高效 cli 工具! 非常感谢 leetcode.com,一个非常棒的网站! ⦙⦙⦙⦙⦙⦙⦙⦙ 一个很打问题的方法。 问题来缓解离线思考。 编码前的源代码。 居住和与 leetcode.com。 下载你...
6. Word Ladder 单词梯是一个字符串问题,要求将一个单词转换为另一个单词,并且每次转换只能改变一个字符。可以使用广度优先搜索或深度优先搜索来解决该问题。 7. Median of Two Sorted Arrays in Java 两个排序...
126.Word_Ladder_II_词语阶梯二【LeetCode单题讲解系列】
leetcode-cli 注意:这个存储库是为了临时使用而分叉的。 注意:从 webbrowser 复制 cookie 并使用leetcode user -c可以临时修复不能。 一个享受 leetcode 的高效 cli 工具! 非常感谢 leetcode.com,一个非常棒的...
这个压缩包“leetcode--python”显然包含了与LeetCode相关的Python解题代码,可能是一个开源项目,用于存储用户或社区成员解决LeetCode问题的Python实现。 **LeetCode概述** LeetCode提供了一系列的算法和数据结构...
leetcode26 algo 算法与数据结构,练习代码 语言:java 8 开发工具:vscode,安装插件Java Extension Pack vscode有智能提示,可调试,有重构支持,满足代码练习要求,相比IDEA更轻量级,普通笔记本即可流畅运行。 ...
leetcode 答案Leetcode---算法 我对 Leetcode 算法问题的回答
leetcode 接口 该项目可帮助您使用首选的 IDE 或带有命令行界面 (CLI) 的编辑器来执行 leetcode。 入门 先决条件 Windows 10、MacOS、Linux Chrome版 >=90.0.4430 安装 # Prepare your virtual environment conda ...
leetcode-machine-swift :SOS_button: 请帮助在Sources/leetcode-machine-swift/leetcode.swift设置所有 leetcode 问题。 :SOS_button: 在 swift 编码时有 xcode 总是好的。 利用自动补全、类型检查...功能可以帮助...