Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) fromstart 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.
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.