Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) fromstart to end, such that:
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:
public class Solution { public ArrayList<ArrayList<String>> res; public String end; public int target_length; public ArrayList<String> temp_list; public ArrayList<ArrayList<String>> findLadders(String start, String end, HashSet<String> dict) { // Start typing your Java solution below // DO NOT write main() function res = new ArrayList<ArrayList<String>>(); temp_list = new ArrayList<String>(); this.end = end; if (start.length() != end.length()) return res; if (start.equals(end)) { temp_list.add(start); temp_list.add(end); res.add(temp_list); return res; } target_length = shortestLength(start, end, dict); int current_length = 1; temp_list.add(start); DFS(start, current_length, dict); return res; } private void DFS(String start, int current_length, HashSet<String> dict) { current_length++; if (current_length > target_length) return; Stack<String> stack = new Stack<String>(); HashSet<String> valid_neighbor = nextHit(start, dict); for (String str : valid_neighbor) stack.push(str); while (!stack.isEmpty()) { String s = stack.pop(); temp_list.add(s); DFS(s, current_length, dict); if (s.equals(end) && current_length == target_length) res.add(new ArrayList<String>(temp_list)); temp_list.remove(temp_list.size() - 1); } } private int shortestLength(String start, String end, HashSet<String> dict) { if (start.length() != end.length()) return 0; if (start.equals(end)) return 2; int path = 0; Queue<String> queue = new LinkedList<String>(); queue.offer(start); HashSet<String> hitted = new HashSet<String>(); hitted.add(start); int queue_counter = 1; while (!queue.isEmpty()) { String s = queue.poll(); queue_counter--; HashSet<String> valid_neighbor = nextHit(s, dict, hitted); for (String str : valid_neighbor) { if (str.equals(end)) return path + 2; else queue.offer(str); } if (queue_counter == 0) { path++; queue_counter = queue.size(); } } return 0; } private HashSet<String> nextHit(String s, HashSet<String> dict, HashSet<String> hitted) { HashSet<String> valid_neighbor = new HashSet<String>(); for (int len = 0; len < s.length(); len++) { StringBuilder sb = new StringBuilder(s); for (char ch = 'a'; ch <= 'z'; ch++) { sb.setCharAt(len, ch); String test_case = sb.toString(); if ((dict.contains(test_case) || test_case.equals(end))&& !hitted.contains(test_case)) { hitted.add(test_case); valid_neighbor.add(test_case); } } } return valid_neighbor; } private HashSet<String> nextHit(String s, HashSet<String> dict) { HashSet<String> valid_neighbor = new HashSet<String>(); for (int len = 0; len < s.length(); len++) { StringBuilder sb = new StringBuilder(s); for (char ch = 'a'; ch <= 'z'; ch++) { sb.setCharAt(len, ch); String test_case = sb.toString(); if (dict.contains(test_case) || test_case.equals(end)) { valid_neighbor.add(test_case); } } } return valid_neighbor; } }String start and end are not included in the dictionary, which is different from Word Ladder I. Need special attention to this factor when generating a valid_neighbor set.
Based on WordLadder I and DFS
Passed on judge small, but failed on judge large.