LeetCode-126. Word Ladder IIhttps://leetcode.com/problems/word-ladder-ii/
题目描述
A transformation sequence from word beginWord
to word endWord
using a dictionary wordList
is a sequence of words beginWord -> s1 -> s2 -> ... -> sk
such that:
- Every adjacent pair of words differs by a single letter.
- Every
si
for1 <= i <= k
is inwordList
. Note thatbeginWord
does not need to be inwordList
. sk == endWord
Given two words, beginWord
and endWord
, and a dictionary wordList
, return all the shortest transformation sequences from beginWord
to endWord
, or an empty list if no such sequence exists. Each sequence should be returned as a list of the words [beginWord, s1, s2, ..., sk]
.
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"]] Explanation: There are 2 shortest transformation sequences: "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 there is no valid transformation sequence.
Constraints:
1 <= beginWord.length <= 5
endWord.length == beginWord.length
1 <= wordList.length <= 1000
wordList[i].length == beginWord.length
-
beginWord
,endWord
, andwordList[i]
consist of lowercase English letters. beginWord != endWord
- All the words in
wordList
are unique.
解题思路
【C++解法】
1. BFS:set + queue + vector
//这里再用map + vector就不合适了
unordered_map<string, vector<string>> mp;
for (string& w:wordList)
for(int i=0; i<w.size(); i++)
mp[w.substr(0, i) + "#" + w.substr(i+1)].push_back(w);
....
mp.erase(key);
很明显dog log都和#og相关,erase会导致另一条路不能再走。
class Solution {
public:
vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
vector< vector<string>> res;
unordered_set<string> dict(wordList.begin(),wordList.end());
if (dict.find(endWord) == dict.end()) {return res;}
queue<vector<string>> q;
q.push({beginWord});
bool flag = false;
while (!q.empty()){
int size = q.size();
while (size--){
vector<string> curPath = q.front(); q.pop();
string last = curPath.back();
if (last == endWord) {
res.push_back(curPath);
flag = true;
continue;
}
dict.erase(last);
for (int i=0; i<last.size(); i++){
string temp = last;
for (char ch='a'; ch<='z'; ch++){
temp[i] = ch;
if (dict.find(temp) != dict.end()){
curPath.push_back(temp);
q.push(curPath);
curPath.pop_back();
}
}
}
}
if (flag) {break;}
}
return res;
}
};
【Java解法】
This solution search from endWord to beginWord, firstly do bfs to get shortest path and store distance and neighbor words infomation, secondly do dfs to get the paths:
1.Use a HashMap to record the distance between every word in wordlist and the beginWord during bfs.
2.Use a HashMap to record the the neighbor words list of the word(direction: from endWord to beginWord) during bfs.
3.Do dfs to add the words on the path and generate the answer.
class Solution {
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
Set<String> words = new HashSet<>(wordList);
List<List<String>> ans = new ArrayList<>();
if (!words.contains(endWord)) {
return ans;
}
Map<String, List<String>> adjWords = new HashMap<>();
Map<String, Integer> dist = new HashMap<>();
bfs(beginWord, adjWords, dist, words);
dfs(endWord, beginWord, adjWords, dist, new ArrayList<>(), ans);
return ans;
}
public void bfs(String beginWord, Map<String, List<String>> adjWords, Map<String, Integer> dist, Set<String> words) {
Queue<String> queue = new LinkedList<>();
queue.offer(beginWord);
dist.put(beginWord, 0);
for (String word : words) {
adjWords.put(word, new ArrayList<>());
}
while (!queue.isEmpty()) {
String cur = queue.poll();
List<String> neighbors = neighbors(cur, words);
for (String next : neighbors) {
adjWords.get(next).add(cur);
if (!dist.containsKey(next)) {
dist.put(next, dist.get(cur) + 1);
queue.offer(next);
}
}
}
}
public void dfs(String curWord, String beginWord,Map<String, List<String>> adjWords, Map<String, Integer> dist, List<String> path, List<List<String>> ans) {
path.add(curWord);
if (curWord.equals(beginWord)) {
Collections.reverse(path);
ans.add(new ArrayList<>(path));
Collections.reverse(path);
} else {
for (String next : adjWords.get(curWord)) {
if (dist.containsKey(next) && dist.get(curWord) == dist.get(next) + 1) {
dfs(next, beginWord, adjWords, dist, path, ans);
}
}
}
path.remove(path.size() - 1);
}
public List<String> neighbors(String word, Set<String> words) {
List<String> ans = new ArrayList<>();
char[] sc = word.toCharArray();
for (int i = 0; i < sc.length; i++) {
char cur = sc[i];
for (char c = 'a'; c <= 'z'; c++) {
sc[i] = c;
String temp = new String(sc);
if (words.contains(temp)) {
ans.add(temp);
}
}
sc[i] = cur;
}
return ans;
}
}