# 0126. Word Ladder II
###### tags: `Leetcode` `Hard` `FaceBook` `DFS` `BFS` `Backtracking`
Link: https://leetcode.com/problems/word-ladder-ii/
## 思路
是[0127. Word Ladder](https://hackmd.io/2F_Qo1tWSH2QKrMp6USYEw)的变种,127题是找出有几条最短路径,126多了要把最短路径print出来
因为找最短路径一定是用BFS,产生所有路径一定是用backtracking,因此我们需要在BFS的时候建一个tree出来,由于在bfs的时候,我们已经构建出了每个单词的neighbor,因此只需要记录每个单词的level数,就可以做backtracking了
这一题找neighbor的方法和在127里面写的不一样,不是用map,而是把26个字母放在每个位子上都尝试一遍,这样找一个word的邻居的时间复杂度是O(26 * M^2) M是字符串长度,因为进了两层回圈之后,还要花O(M),因为要产生新的字符串,才能去set里面看有没有contain
如果用127题的写法,构建map的时间复杂度是O(M^2 * N) N是word个数,然后每次找一个word的neighbor的时间复杂度是O(M^2),因为对于每一个char位置,都需要用*替换,一共替换M次,同时每次替换因为要产生新的字符串,还需要花O(M),因此相比之下,还是这题用的找neighbor的方法时间复杂度比较好
另外,一个de了很久的bug,是原本在57行后面,直接return了,没有先```curr.remove(curr.size-1)```,所以**backtracking一定要记得如果前面改了什么东西,return之前一定要改回去**
## Code
```java=
class Solution {
Map<String, List<String>> adjacentList;
Set<String> dict;
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
adjacentList = new HashMap<>();
dict = new HashSet<>(wordList);
Map<String, Integer> distance = new HashMap<>();
bfs(beginWord, endWord, distance);
List<List<String>> ans = new ArrayList<>();
List<String> curr = new ArrayList<>();
backtracking(beginWord, endWord, distance, curr, ans);
return ans;
}
public void bfs(String beginWord, String endWord, Map<String, Integer> distance){
Set<String> visited = new HashSet<>();
Queue<String> q = new LinkedList<>();
q.add(beginWord);
int dist = 0;
boolean findEnd = false;
while(!q.isEmpty()){
int size = q.size();
for(int i = 0;i < size;i++){
String curr = q.poll();
if(visited.contains(curr)) continue;
visited.add(curr);
distance.put(curr, dist);
// System.out.println(curr+" "+dist);
if(endWord.equals(curr)) findEnd = true;
getNeighbors(curr, dict);
q.addAll(adjacentList.get(curr));
}
dist++;
if(findEnd){
return;
}
}
}
public void getNeighbors(String word, Set<String> dict){
List<String> neighbor = new ArrayList<>();
char[] charArray = word.toCharArray();
for(int i = 0;i < charArray.length;i++){
for(char ch='a'; ch<='z';ch++){
if(charArray[i] == ch) continue;
char oldChar = charArray[i];
charArray[i] = ch;
if(dict.contains(String.valueOf(charArray))){
neighbor.add(String.valueOf(charArray));
}
charArray[i] = oldChar;
}
}
adjacentList.put(word, neighbor);
}
public void backtracking(String startWord, String endWord, Map<String, Integer> distance, List<String> curr, List<List<String>> ans){
curr.add(startWord);
if(startWord.equals(endWord)){
ans.add(new ArrayList<>(curr));
}
else{
for(String next:adjacentList.get(startWord)){
if(!distance.containsKey(next)) continue;
if(distance.get(next) == distance.get(startWord)+1){
// System.out.println(startWord+" "+next);
backtracking(next, endWord, distance, curr, ans);
}
}
}
curr.remove(curr.size()-1);
}
}
```