原题网址:https://leetcode.com/problems/word-ladder-ii/
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 intermediate word must exist in the word list
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["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.
方法一:广度优先搜索,递推实现。
public class Solution {
public List<List<String>> findLadders(String beginWord, String endWord, Set<String> wordList) {
List<List<String>> ladders = new ArrayList<>();
Map<String, List<String>> maskedWords = new HashMap<>();
wordList.add(beginWord);
wordList.add(endWord);
for(String word: wordList) {
char[] wa = word.toCharArray();
for(int i=0; i<wa.length; i++) {
char ch = wa[i];
wa[i] = '*';
String mask = new String(wa);
wa[i] = ch;
List<String> words = maskedWords.get(mask);
if (words == null) {
words = new ArrayList<>();
maskedWords.put(mask, words);
}
words.add(word);
}
}
wordList.remove(beginWord);
List<Ladder> currents = new ArrayList<>();
currents.add(new Ladder(beginWord, null));
int from = 0;
int to = 1;
BFS: while (from < currents.size()) {
to = currents.size();
for(int i=from; i<to; i++) {
String word = currents.get(i).word;
if (word.equals(endWord)) {
break BFS;
}
char[] wa = word.toCharArray();
for(int j=0; j<wa.length; j++) {
char ch = wa[j];
wa[j] = '*';
String mask = new String(wa);
wa[j] = ch;
List<String> words = maskedWords.get(mask);
for(String w: words) {
if (wordList.contains(w)) {
currents.add(new Ladder(w, currents.get(i)));
}
}
}
}
from = to;
for(int i=to; i<currents.size(); i++) {
wordList.remove(currents.get(i).word);
}
}
if (from < currents.size()) {
for(int i=from; i<to; i++) {
String word = currents.get(i).word;
if (!word.equals(endWord)) continue;
LinkedList<String> ladder = new LinkedList<>();
Ladder l = currents.get(i);
do {
ladder.addFirst(l.word);
l = l.prev;
} while (l != null);
ladders.add(ladder);
}
}
return ladders;
}
}
class Ladder {
String word;
Ladder prev;
Ladder(String word, Ladder prev) {
this.word = word;
this.prev = prev;
}
}
方法二:广度优先搜索,关键是搜索完整一层之后,再删除相关节点。
public class Solution {
private List<List<String>> find(List<Ladder> ladders, String endWord, Set<String> wordList) {
List<List<String>> results = new ArrayList<>();
for(Ladder ladder : ladders) {
if (ladder.word.equals(endWord)) {
List<String> result = new ArrayList<>();
while (ladder != null) {
result.add(0, ladder.word);
ladder = ladder.prev;
}
results.add(result);
}
}
if (!results.isEmpty()) return results;
List<Ladder> nexts = new ArrayList<>();
for(Ladder ladder : ladders) {
char[] la = ladder.word.toCharArray();
for(int i=0; i<la.length; i++) {
char origin = la[i];
for(char ch = 'a'; ch <= 'z'; ch ++) {
if (ch == origin) continue;
la[i] = ch;
String s = new String(la);
if (wordList.contains(s)) nexts.add(new Ladder(s, ladder));
}
la[i] = origin;
}
}
if (nexts.isEmpty()) return new ArrayList<>();
for(Ladder ladder : nexts) wordList.remove(ladder.word);
return find(nexts, endWord, wordList);
}
public List<List<String>> findLadders(String beginWord, String endWord, Set<String> wordList) {
wordList.remove(beginWord);
List<Ladder> ladders = new ArrayList<>();
ladders.add(new Ladder(beginWord, null));
return find(ladders, endWord, wordList);
}
}
class Ladder {
String word;
Ladder prev;
Ladder(String word, Ladder prev) {
this.word = word;
this.prev = prev;
}
}