126. Word Ladder II
by Botao Xiao
Question:
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.
Note:
- Return an empty list if there is no such transformation sequence.
- All words have the same length.
- All words contain only lowercase alphabetic characters.
- You may assume no duplicates in the word list.
- You may assume beginWord and endWord are non-empty and are not the same.
Example 1:
Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
Output:
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Example 2:
Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Output: []
Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
Solutions
- Method 1: dfs TLE
class Solution { private int min = Integer.MAX_VALUE >> 1; public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) { List<List<String>> result = new ArrayList<>(); Set<String> words = new HashSet<>(wordList); if(!words.contains(endWord)) return result; int len = beginWord.length(); List<String> temp = new ArrayList<String>(); temp.add(beginWord); dfs(result, words, len, endWord, beginWord, temp); return result; } private void dfs(List<List<String>> result, Set<String> words, int len, String endWord, String cur, List<String> temp){ if(cur.equals(endWord)){ if(temp.size() < min){ result.clear(); min = temp.size(); } result.add(new ArrayList<String>(temp)); }else if(temp.size() < min){ for(int i = 0; i < len; i++){ char[] arr = cur.toCharArray(); for(char c = 'a'; c <= 'z'; c++){ arr[i] = c; String next = new String(arr); if(words.contains(next)){ words.remove(next); temp.add(next); dfs(result, words, len, endWord, next, temp); temp.remove(temp.size() - 1); words.add(next); } } arr[i] = cur.charAt(i); } } } }
- Method 2: bfs AC
class Solution { private Map<String, List<String>> map; public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) { List<List<String>> result = new LinkedList<>(); Set<String> words = new HashSet<>(wordList); if(!words.contains(endWord)) return result; words.remove(beginWord); LinkedList<String> queue = new LinkedList<>(); map = new HashMap<>(); int len = beginWord.length(); boolean found = false; queue.add(beginWord); while(!queue.isEmpty() && !found){ int size = queue.size(); Set<String> curLevel = new HashSet<>(); for(int i = 0; i < size; i++){ String cur = queue.poll(); if(cur.equals(endWord)) found = true; char[] arr = cur.toCharArray(); for(int l = 0; l < len; l++){ for(char c = 'a'; c <= 'z'; c++){ if(c == cur.charAt(l)) continue; arr[l] = c; String next = new String(arr); if(words.contains(next) || curLevel.contains(next)){ map.put(cur, !map.containsKey(cur) ? new ArrayList<String>(): map.get(cur)); map.get(cur).add(next); curLevel.add(next); if(words.contains(next)) queue.offer(next); words.remove(next); } } arr[l] = cur.charAt(l); } } } List<String> temp = new LinkedList<>(); temp.add(beginWord); dfs(result, temp, endWord, beginWord); return result; } private void dfs(List<List<String>> result, List<String> temp, String endWord, String cur){ if(cur.equals(endWord)){ result.add(new ArrayList<>(temp)); }else{ if(!map.containsKey(cur)) return; List<String> adj = map.get(cur); for(String s: adj){ temp.add(s); dfs(result, temp, endWord, s); temp.remove(temp.size() - 1); } } } }
Amazon session
class Solution {
private List<List<String>> result;
private Map<String, Set<String>> map;
private String endWord;
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
Set<String> words = new HashSet<>(wordList);
this.result = new ArrayList<>();
if(!words.contains(endWord)) return result;
Queue<String> q = new LinkedList<>();
this.map = new HashMap<>();
this.endWord = endWord;
q.offer(beginWord);
boolean found = false;
int step = 0;
int len = beginWord.length();
while(!q.isEmpty() && !found){
int size = q.size();
Set<String> curLevel = new HashSet<>();
step++;
for(int k = 0; k < size; k++){
String cur = q.poll();
if(cur.equals(endWord)) found = true;
char[] arr = cur.toCharArray();
for(int i = 0; i < len; i++){
char origin = arr[i];
for(char c = 'a'; c <= 'z'; c++){
if(c == origin) continue;
arr[i] = c;
String next = new String(arr);
if(words.contains(next) || curLevel.contains(next)){
curLevel.add(next);
words.remove(next);
Set<String> set = map.getOrDefault(cur, new HashSet<>());
set.add(next);
map.put(cur, set);
q.offer(next);
}
}
arr[i] = origin;
}
}
}
List<String> res = new ArrayList<>();
res.add(beginWord);
Set<String> visited = new HashSet<>();
visited.add(beginWord);
dfs(beginWord, res, step, visited);
return this.result;
}
private void dfs(String cur, List<String> temp, int step, Set<String> visited){
int size = temp.size();
if(cur.equals(endWord)){
this.result.add(new ArrayList<>(temp));
}else if(size < step){
if(!map.containsKey(cur)) return;
Set<String> neighbour = map.get(cur);
for(String n : neighbour){
if(visited.contains(n)) continue;
temp.add(n);
visited.add(n);
dfs(n, temp, step, visited);
visited.remove(n);
temp.remove(temp.size() - 1);
}
}
}
}
Subscribe via RSS