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.
https://oj.leetcode.com/problems/word-ladder-ii/
思路:这道题主要是超时的问题,java的时间卡的比较紧。整体思路还是bfs求最短路径,同时记录下pre节点用于最后从end节点dfs得到所有路径。
注意因为同一个单词可能在不同的路径中以相同的路径长度出现,所以用完之后不能从dict中删除,对于再次到达已经遍历过的节点,如果距离超过之前的距离则忽略,如果距离相同,也需要添加到pre中(比如例子中的cog对象)。
import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.Map; import java.util.Queue; public class Solution { public ArrayList<ArrayList<String>> findLadders(String start, String end, HashSet<String> dict) { dict.add(end); ArrayList<ArrayList<String>> res = new ArrayList<ArrayList<String>>(); HashMap<String, Node> map = new HashMap<String, Node>(); Queue<String> queue = new LinkedList<String>(); queue.add(start); Node startNode = new Node(1, start); startNode.pre.add(null); map.put(start, startNode); while (!queue.isEmpty()) { String cur = queue.remove(); Node curNode = map.get(cur); // found if (cur.equals(end)) { getPaths(map.get(end), map, new ArrayList<String>(), res); return res; } for (int i = 0; i < cur.length(); i++) { for (int j = 0; j < 26; j++) { String newStr = makeNewStr(i, j, cur); if (newStr.equals(cur)) continue; if (dict.contains(newStr)) { if (!map.containsKey(newStr)) { Node newNode = new Node(curNode.dist + 1, newStr); newNode.pre.add(curNode); map.put(newStr, newNode); queue.add(newStr); } else {// different path with the same length Node oldNewNode = map.get(newStr); if (oldNewNode.dist == curNode.dist + 1) { oldNewNode.pre.add(curNode); } } } } } } return res; } private void getPaths(Node end, Map<String, Node> map, ArrayList<String> curPath, ArrayList<ArrayList<String>> paths) { if (end == null) { paths.add(new ArrayList<String>(curPath)); return; } for (Node prevNode : end.pre) { curPath.add(0, end.str); getPaths(prevNode, map, curPath, paths); curPath.remove(0); } } private String makeNewStr(int i, int j, String cur) { StringBuilder sb = new StringBuilder(cur); sb.setCharAt(i, (char) ('a' + j)); return sb.toString(); } public static void main(String[] args) { HashSet<String> set = new HashSet<String>(); String[] a = { "hot", "dot", "dog", "lot", "log" }; for (String each : a) set.add(each); System.out.println(new Solution().findLadders("hit", "cog", set)); } private static class Node { public int dist; public String str; public LinkedList<Node> pre = new LinkedList<Node>();; public Node(int dist, String str) { this.dist = dist; this.str = str; } public void addPrev(Node pNode) { pre.add(pNode); } @Override public String toString() { return "Node [dist=" + dist + ", str=" + str + ", prev=" + pre + "]"; } } }
参考: