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 intermediate word must exist in the word list
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Return
[ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ]
import java.util.*;
public class Solution {
public List<List<String>> findLadders(String start, String end, Set<String> dict) {
List<List<String>> ladders = new ArrayList<List<String>>();
Map<String, List<String>> map = new HashMap<String, List<String>>();
Map<String, Integer> distance = new HashMap<String, Integer>();
dict.add(start);
dict.add(end);
bfs(map, distance, start, end, dict);
List<String> path = new ArrayList<String>();
dfs(ladders, path, end, start, distance, map);
return ladders;
}
void dfs(List<List<String>> ladders, List<String> path, String crt, String start, Map<String, Integer> distance,
Map<String, List<String>> map) {
path.add(crt);
if (crt.equals(start)) {
Collections.reverse(path);
ladders.add(new ArrayList<String>(path));
Collections.reverse(path);
} else {
for (String next : map.get(crt)) {
if (distance.containsKey(next) && distance.get(crt) == distance.get(next) + 1) {
dfs(ladders, path, next, start, distance, map);
}
}
}
path.remove(path.size() - 1);
}
void bfs(Map<String, List<String>> map, Map<String, Integer> distance, String start, String end, Set<String> dict) {
Queue<String> q = new LinkedList<String>();
q.offer(start);
distance.put(start, 0);
for (String s : dict) {
map.put(s, new ArrayList<String>());
}
while (!q.isEmpty()) {
String crt = q.poll();
List<String> nextList = expand(crt, dict);
for (String next : nextList) {
map.get(next).add(crt);
if (!distance.containsKey(next)) {
distance.put(next, distance.get(crt) + 1);
q.offer(next);
}
}
}
}
//在dict中找,看crt替换单个字符后有没有在dict中的,如果有,放在expansion中
List<String> expand(String crt, Set<String> dict) {
List<String> expansion = new ArrayList<String>();
for (int i = 0; i < crt.length(); i++) {
for (char ch = 'a'; ch <= 'z'; ch++) {
if (ch != crt.charAt(i)) {
String expanded = crt.substring(0, i) + ch + crt.substring(i + 1);
if (dict.contains(expanded)) {
expansion.add(expanded);
}
}
}
}
return expansion;
}
public static void main(String[] args) {
Solution solution = new Solution();
String start = "hit";
String end = "cog";
Set<String> dict = new HashSet<>();
dict.add("hot");
dict.add("dot");
dict.add("dog");
dict.add("lot");
dict.add("log");
List res = solution.findLadders("hit", "cog", dict);
System.out.println(res);
}
}