Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:
- Only one letter can be changed at a time
- Each intermediate word must exist in the dictionary
For example,
Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
Return
[ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ]
Note:
- All words have the same length.
- All words contain only lowercase alphabetic characters.
private void getNextWords(Map<String, Set<String>> nextWordsMap, String word, Set<String> dict) {
char [] chars = word.toCharArray();
for (int i = 0; i < word.length(); i++) {
char old = chars[i];
for (char c = 'a'; c <= 'z'; c++) {
//do not add the current word
if (c != old) {
chars[i] = c;
String nextWord = new String(chars);
if (dict.contains(nextWord)) {
Set<String> nextWords = nextWordsMap.get(word);
if (nextWords != null) {
nextWords.add(nextWord);
} else {
nextWords = new HashSet<String>();
nextWords.add(nextWord);
nextWordsMap.put(word, nextWords);
}
}
}
}
//revert the word back
chars[i] = old;
}
}
public List<List<String>> findLadders(String start, String end, Set<String> dict) {
List<List<String>> results = new ArrayList<List<String>>();
Queue<String> queue = new LinkedList<String>();
Map<String, Integer> levelMap = new HashMap<String, Integer>();
queue.add(start);
levelMap.put(start, 1);
//make sure the end is in dict
dict.add(end);
Map<String, Set<String>> nextWordsMap = new HashMap<String, Set<String>>();
getNextWords(nextWordsMap, start, dict);
// init adjacent graph
for(String word : dict){
getNextWords(nextWordsMap, word, dict);
}
while (!queue.isEmpty()) {
String wordPath = queue.poll();
String[] words = wordPath.split(" ");
String current = words[words.length-1];
if (current.equals(end)) {
List<String> result = Arrays.asList(words);
results.add(result);
} else {
Set<String> nextWords = nextWordsMap.get(current);
if (nextWords!=null) {
int nextLevel = words.length+1;
for (String nextWord : nextWords) {
//if the word has been used before then he can only be added to the same level
if (levelMap.get(nextWord)==null || nextLevel==levelMap.get(nextWord)) {
queue.add(wordPath + " " + nextWord);
if (levelMap.get(nextWord)==null) {
levelMap.put(nextWord, nextLevel);
}
}
}
}
}
}
return results;
}