|
@@ -1,40 +1,66 @@
|
|
|
import java.util.*;
|
|
|
|
|
|
class Solution {
|
|
|
- private int min;
|
|
|
+ private List<List<String>> res;
|
|
|
+ private List<List<Integer>> prev;
|
|
|
+ private List<String> wordList;
|
|
|
+ private String beginWord;
|
|
|
|
|
|
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
|
|
|
- List<List<String>> res = new ArrayList<>();
|
|
|
- int begIdx = -1, endIdx = -1;
|
|
|
+ res = new ArrayList<>();
|
|
|
+ prev = new ArrayList<>();
|
|
|
+ this.wordList = wordList;
|
|
|
+ this.beginWord = beginWord;
|
|
|
+ int[] dist = new int[wordList.size()];
|
|
|
+ boolean[] used = new boolean[wordList.size()];
|
|
|
+ int endIdx = -1;
|
|
|
+ List<Integer> queue = new ArrayList<>();
|
|
|
for (int i = 0; i < wordList.size(); i++) {
|
|
|
+ prev.add(new ArrayList<>());
|
|
|
String word = wordList.get(i);
|
|
|
- if (word.equals(beginWord)) begIdx = i;
|
|
|
if (word.equals(endWord)) endIdx = i;
|
|
|
+ if (isConvertible(beginWord, word)) {
|
|
|
+ used[i] = true;
|
|
|
+ prev.get(i).add(-1);
|
|
|
+ dist[i] = 1;
|
|
|
+ queue.add(i);
|
|
|
+ }
|
|
|
}
|
|
|
- if (begIdx == -1) begIdx = wordList.size();
|
|
|
if (endIdx == -1) return res;
|
|
|
- // Create adj matrix
|
|
|
- int n = Math.max(wordList.size(), begIdx + 1);
|
|
|
- List<List<Integer>> adj = new ArrayList<>();
|
|
|
- for (int i = 0; i < n; i++) adj.add(new ArrayList<>());
|
|
|
- for (int i = 0; i < n; i++) {
|
|
|
- List<Integer> li = adj.get(i);
|
|
|
- String w1 = i == begIdx ? beginWord : wordList.get(i);
|
|
|
- for (int j = 0; j < wordList.size(); j++) {
|
|
|
- String w2 = wordList.get(j);
|
|
|
- if (isConvertible(w1, w2)) li.add(j);
|
|
|
+ while (!queue.isEmpty()) {
|
|
|
+ List<Integer> newQueue = new ArrayList<>();
|
|
|
+ for (Integer i : queue) {
|
|
|
+ for (int j = 0; j < wordList.size(); j++) {
|
|
|
+ if (used[j]) continue;
|
|
|
+ if (!isConvertible(wordList.get(i), wordList.get(j))) continue;
|
|
|
+ prev.get(j).add(i);
|
|
|
+ if (dist[j] != 0) continue;
|
|
|
+ dist[j] = dist[i] + 1;
|
|
|
+ newQueue.add(j);
|
|
|
+ }
|
|
|
}
|
|
|
+ queue = newQueue;
|
|
|
+ for (Integer i : queue) used[i] = true;
|
|
|
}
|
|
|
- // Init path
|
|
|
- min = Integer.MAX_VALUE;
|
|
|
- List<String> path = new ArrayList<>();
|
|
|
- path.add(beginWord);
|
|
|
- boolean[] used = new boolean[wordList.size()];
|
|
|
- if (begIdx < wordList.size()) used[begIdx] = true;
|
|
|
- dfs(adj, wordList, res, path, used, begIdx, endIdx);
|
|
|
+ dfs(endIdx, new ArrayList<String>());
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
+ private void dfs(int idx, List<String> path) {
|
|
|
+ List<String> newPath = new ArrayList<>();
|
|
|
+ if (idx == -1) {
|
|
|
+ newPath.add(beginWord);
|
|
|
+ newPath.addAll(path);
|
|
|
+ res.add(newPath);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ newPath.add(wordList.get(idx));
|
|
|
+ newPath.addAll(path);
|
|
|
+ for (Integer i : prev.get(idx)) {
|
|
|
+ dfs(i, newPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private boolean isConvertible(String w1, String w2) {
|
|
|
int cnt = 0;
|
|
|
for (int i = 0; i < w1.length(); i++) {
|
|
@@ -42,27 +68,4 @@ class Solution {
|
|
|
}
|
|
|
return cnt == 1;
|
|
|
}
|
|
|
-
|
|
|
- private void dfs(List<List<Integer>> adj, List<String> words, List<List<String>> res, List<String> path, boolean[] used, int idx, int endIdx) {
|
|
|
- if (min < path.size()) return;
|
|
|
- if (idx == endIdx) {
|
|
|
- if (path.size() < min) {
|
|
|
- res.clear();
|
|
|
- min = path.size();
|
|
|
- }
|
|
|
- List<String> copy = new ArrayList<>();
|
|
|
- copy.addAll(path);
|
|
|
- res.add(copy);
|
|
|
- return;
|
|
|
- }
|
|
|
- List<Integer> li = adj.get(idx);
|
|
|
- for (Integer next : li) {
|
|
|
- if (used[next]) continue;
|
|
|
- used[next] = true;
|
|
|
- path.add(words.get(next));
|
|
|
- dfs(adj, words, res, path, used, next, endIdx);
|
|
|
- used[next] = false;
|
|
|
- path.remove(path.size() - 1);
|
|
|
- }
|
|
|
- }
|
|
|
}
|