Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情
一、题目描述:
按字典 wordList 完成从单词 beginWord 到单词 endWord 转化,一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> ... -> sk 这样的单词序列,并满足:
每对相邻的单词之间仅有单个字母不同。
转换过程中的每个单词 si(1 <= i <= k)必须是字典 wordList 中的单词。注意,beginWord 不必是字典 wordList 中的单词。 sk == endWord
给你两个单词 beginWord 和 endWord ,以及一个字典 wordList 。请你找出并返回所有从 beginWord 到 endWord 的 最短转换序列 ,如果不存在这样的转换序列,返回一个空列表。每个序列都应该以单词列表 [beginWord, s1, s2, ..., sk] 的形式返回。
示例 1:
输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出:[["hit","hot","dot","dog","cog"],["hit","hot","lot","log","cog"]]
解释:存在 2 种最短的转换序列:
"hit" -> "hot" -> "dot" -> "dog" -> "cog"
"hit" -> "hot" -> "lot" -> "log" -> "cog"
示例 2:
输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出:[]
解释:endWord "cog" 不在字典 wordList 中,所以不存在符合要求的转换序列。
二、思路与实现:
思路:
通过使用双向BFS + 入队节点,构建正方向的有向无环图 dag。 DFS 在 dag 中收集所有连通路径(路径只要连通就是最短),记忆当前节点到终点的路径
代码实现:
/**
* @param {string} beginWord
* @param {string} endWord
* @param {string[]} wordList
* @return {string[][]}
*/
var findLadders = function(beginWord, endWord, wordList) {
let wordSet = new Set(wordList);
if (!wordSet.has(endWord)) return [];
wordSet.delete(beginWord);
let beginSet = new Set([beginWord]);
let map = new Map();
let distance = 0;
let minDistance = 0;
while(beginSet.size) {
if (beginSet.has(endWord)) break;
let trySet = new Set();
for (let word of beginSet) {
let mapSet = new Set();
for (let i = 0; i < word.length; i++) {
for (let j = 0; j < 26; j++) {
let tryWord = word.slice(0, i) + String.fromCharCode(97 + j) + word.slice(i + 1);
if (!minDistance && tryWord === endWord) minDistance = distance + 1;
if (wordSet.has(tryWord)) {
trySet.add(tryWord);
mapSet.add(tryWord);
}
}
}
map.set(word, mapSet);
}
distance++;
for (let w of trySet) {
wordSet.delete(w);
}
beginSet = trySet;
}
let ans = [];
let path = [beginWord];
dfs(beginWord, endWord, ans, path, map, minDistance, 0);
return ans;
};
function dfs (beginWord, endWord, ans, path, map, minDistance, distance) {
if (distance > minDistance) return ;
if (beginWord === endWord) {
ans.push(path.slice());
}
let words = map.get(beginWord)
if (words) {
for (let word of words) {
path.push(word)
dfs(word, endWord, ans, path, map, minDistance, distance + 1);
path.pop();
}
}
}
三、总结:
本题先用 BFS 求出最短距离,再用 DFS 求出最短距离路径即得解。BFS 和 DFS 是真的重要呀~