126. Word Ladder II
hard
create nextMap by 26 letters (T = O(26NK) -> create adjList by BFS (T = O(N(N-1)) -> backtracking to get all shortest path (T = O(paths). In total, T = O(N^2). But leetcode says T = O(NK^2 + paths).
It's a directed graph, N vertex has at most (N-1) edges, K is the length of word.
class Solution {
Map<String, List<String>> map = new HashMap<>();
Map<String, List<String>> adjList = new HashMap<>();
List<List<String>> solutions = new ArrayList<List<String>>();
int shortest = Integer.MAX_VALUE;
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
if(!wordList.contains(endWord))
return solutions;
List<String> solution = new ArrayList<String>();
solution.add(beginWord);
if(wordList.contains(beginWord)) {
wordList.remove(beginWord);
}
createMap(beginWord, wordList);
System.out.println(map);
createAdjList(beginWord, endWord);
System.out.println(adjList);
backtrack(beginWord, endWord, solution, new ArrayList<String>());
return solutions;
}
private void createMap(String beginWord, List<String> wordList) {
List<String> nextWord = findNext(wordList, beginWord);
map.put(beginWord, nextWord);
for(int i = 0; i < wordList.size(); i ++) {
nextWord = findNext(wordList, wordList.get(i));
map.put(wordList.get(i), nextWord);
}
}
private List<String> findNext(List<String> wordList, String word) {
String letters = "abcdefghijklmnopqrstuvwxyz";
List<String> next = new ArrayList<>();
for(int i = 0; i < word.length(); i ++) {
for(int j = 0; j < letters.length(); j ++) {
String newWord = word.substring(0, i) + letters.charAt(j) + word.substring(i+1, word.length());
if(!newWord.equals(word) && wordList.contains(newWord))
next.add(newWord);
}
}
return next;
}
private void createAdjList(String beginWord, String endWord) {
Queue<String> q = new LinkedList<String>();
q.add(beginWord);
Map<String, Integer> visited = new HashMap<String, Integer>();
int layer = 0;
while(q.size() > 0) {
int l = q.size();
for(int i = 0; i < l; i++) {
String currWord = q.poll();
adjList.put(currWord, new ArrayList<String>());
List<String> next = map.get(currWord);
for(String s: next) {
if(visited.containsKey(s) && visited.get(s) != layer)
continue;
visited.put(s, layer);
adjList.get(currWord).add(s);
q.add(s);
}
}
layer ++;
}
}
private void backtrack(String beginWord, String endWord, List<String> solution, List<String> visited) {
// stop condition
if(solution.contains(endWord)) {
if(solution.size() < shortest) {
solutions.clear();
solutions.add(new ArrayList<String>(solution));
shortest = solution.size();
} else if(solution.size() == shortest)
solutions.add(new ArrayList<String>(solution));
return;
}
// regular case
for(String next: adjList.get(beginWord)) {
if(!visited.contains(next) && solution.size() < shortest) {
solution.add(next);
visited.add(next);
backtrack(next, endWord, solution, visited);
solution.remove(next);
visited.remove(next);
}
}
}
}
Last updated
Was this helpful?