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 transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
Return
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
题意:127题的followup,要求不单是求最少变换次数,还要返回所有符合最短变换次数的具体变换。
思路:
先用bfs找寻最短路径,同时为每个单词标上它的最短等级;
然后用dfs搜索所有最短路径,搜索的条件就是下一个单词的最短等级等于当前单词最短等级+1.
public List> findLadders(String beginWord, String endWord, List wordList) {
HashSet dict = new HashSet<>(wordList);
dict.add(beginWord);
HashMap depth = new HashMap<>();
HashMap> neighbours = new HashMap<>();
for (String word : wordList) {
neighbours.put(word, new ArrayList<>());
}
neighbours.put(beginWord, new ArrayList<>());
List> res = new ArrayList<>();
List subres = new ArrayList<>();
bfs(beginWord, endWord, dict, depth, neighbours);
dfs(beginWord, endWord, dict, neighbours, depth, subres, res);
return res;
}
public void bfs(String beginWord, String endWord, HashSet dict, HashMap depth, HashMap> neighbours) {
Queue q = new LinkedList<>();
q.add(beginWord);
depth.put(beginWord, 0);
while (!q.isEmpty()) {
int size = q.size();
boolean found = false;
for (int i = 0; i < size; i++) {
String cur = q.poll();
int curDistance = depth.get(cur);
List nextWords = getNextWords(cur, dict);
for (String nextWord : nextWords) {
neighbours.get(cur).add(nextWord);
if (!depth.containsKey(nextWord)) {
depth.put(nextWord, curDistance + 1);
if (endWord.equals(nextWord)) {
found = true;
} else {
q.offer(nextWord);
}
}
}
}
if (found) {
break;
}
}
}
//bug 这里不能过滤掉depth中已经有的word,否则会导致某些词的neighbours有缺失
// public List
public List
List
char[] chars = word.toCharArray();
for (int i = 0; i < word.length(); i++) {
for (char c = 'a'; c <= 'z'; c++) {
if (chars[i] == c) {
continue;
}
char origin = chars[i];
chars[i] = c;
String nextWord = new String(chars);
// if (dict.contains(nextWord) && !depth.containsKey(nextWord)) {
if (dict.contains(nextWord)) {
list.add(nextWord);
}
chars[i] = origin;
}
}
return list;
}
private void dfs(String cur, String end, Set dict, HashMap> nodeNeighbors, HashMap distance, List solution, List> res) {
solution.add(cur);
if (end.equals(cur)) {
res.add(new ArrayList<>(solution));
} else {
List neighbours = nodeNeighbors.get(cur);
for (String next : nodeNeighbors.get(cur)) {
if (distance.get(next) == distance.get(cur) + 1) {
dfs(next, end, dict, nodeNeighbors, distance, solution, res);
}
}
}
solution.remove(solution.size() - 1);
}