Problem
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
Notice
All words have the same length.
All words contain only lowercase alphabetic characters.
Example
Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
Return
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Solution DFS+BFS
Updated 2018-11
class Solution {
public List<List<String>> findLadders(String start, String end, List<String> wordList) {
List<List<String>> res = new ArrayList<>();
Set<String> dict = new HashSet<>(wordList);
if (!dict.contains(end)) return res;
//save shortest distance from start to each node
Map<String, Integer> distanceMap = new HashMap<>();
//save all the nodes can be transformed from each node
Map<String, List<String>> neighborMap = new HashMap<>();
dict.add(start);
//use bfs to: find the shortest distance; update neighborMap and distanceMap
bfs(start, end, dict, neighborMap, distanceMap);
//use dfs to: output all the paths with the shortest distance
dfs(start, end, neighborMap, distanceMap, new ArrayList<>(), res);
return res;
}
private void bfs(String start, String end, Set<String> dict, Map<String, List<String>> neighborMap, Map<String, Integer> distanceMap) {
for (String str: dict) {
neighborMap.put(str, new ArrayList<>());
}
Deque<String> queue = new ArrayDeque<>();
queue.offer(start);
distanceMap.put(start, 0);
while (!queue.isEmpty()) {
int size = queue.size();
boolean foundEnd = false;
for (int i = 0; i < size; i++) {
String cur = queue.poll();
int curDist = distanceMap.get(cur);
List<String> neighbors = getNeighbors(dict, cur);
for (String neighbor: neighbors) {
neighborMap.get(cur).add(neighbor);
if (!distanceMap.containsKey(neighbor)) {
distanceMap.put(neighbor, curDist+1);
if (neighbor.equals(end)) foundEnd = true;
else queue.offer(neighbor);
}
}
}
if (foundEnd) break;
}
}
private void dfs(String start, String end, Map<String, List<String>> neighborMap, Map<String, Integer> distanceMap, List<String> temp, List<List<String>> res) {
if (start.equals(end)) {
temp.add(start);
res.add(new ArrayList<>(temp));
temp.remove(temp.size()-1);
}
for (String neighbor: neighborMap.get(start)) {
temp.add(start);
if (distanceMap.get(neighbor) == distanceMap.get(start)+1) {
dfs(neighbor, end, neighborMap, distanceMap, temp, res);
}
temp.remove(temp.size()-1);
}
}
private List<String> getNeighbors(Set<String> dict, String str) {
List<String> res = new ArrayList<>();
for (int i = 0; i < str.length(); i++) {
StringBuilder sb = new StringBuilder(str);
for (char ch = 'a'; ch <= 'z'; ch++) {
sb.setCharAt(i, ch);
String neighbor = sb.toString();
if (dict.contains(neighbor)) res.add(neighbor);
}
}
return res;
}
}
Solution
Note
- result: 存放transformation过程中的所有List<String>集合
- map: key为所有transformation的结尾String,value则顺序存放这个结尾String对应的transformation中的所有String
- queue: 存放同一个循环level的新加入的String,在下一个循环再依次对其中元素进行进一步的BFS
- preList: 把首个字符串start放入新List,再将List放入res,并将start-res键值对放入map,进行初始化
public class Solution {
public List<List<String>> findLadders(String start, String end, Set<String> dict) {
List<List<String>> res = new ArrayList<>();
List<String> preList = new ArrayList<>();
Queue<String> queue = new LinkedList<>();
Map<String, List<List<String>>> map = new HashMap<>();
preList.add(start);
queue.offer(start);
res.add(preList);
map.put(start, res);
while (!queue.isEmpty()) {
String pre = queue.poll();
if (pre.equals(end)) return map.get(pre);
for (int i = 0; i < pre.length(); i++) {
for (int j = 0; j < 26; j++) {
StringBuilder sb = new StringBuilder(pre);
sb.setCharAt(i,(char) ('a'+j));
String cur = sb.toString();
if (!cur.equals(pre) && dict.contains(cur) && (!map.containsKey(cur) || map.get(pre).get(0).size()+1 <= map.get(cur).get(0).size())) {
List<List<String>> temp = new ArrayList<>();
for (List<String> p: map.get(pre)) {
List<String> curList = new ArrayList<>(p);
curList.add(cur);
temp.add(curList);
}
if (!map.containsKey(cur)) {
map.put(cur, temp);
queue.offer(cur);
}
else if (map.get(pre).get(0).size()+1 < map.get(cur).get(0).size()) map.put(cur, temp);
else map.get(cur).addAll(temp);
}
}
}
}
return res.get(0).size() > 1 ? res : new ArrayList<List<String>>();
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。