持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【LeetCode 126. 单词接龙 II 】- JavaScript(BFS+DFS)
题目描述
按字典 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"
DFS+BFS
思路分析:
整体的的思路:分析完这个题目之后就知道我们应该使用DFS和BFS结合来做,首先我们要做的是构建出这个无向无权图,根绝题意我们可以知道,与一个word相差一个字母的单词都是该word的邻居节点。后面补充这里如何操作效率会高。我们将该图建立起来之后,通过BFS一层层的遍历,在遍历的过程中我们可以轻松的得到每个单词举例beginWord的层次信息 wordLevel。以及每个word的父亲节点(即与该节点相连的节点是那些)wordConnection.根绝这两个信息,可以帮助我们快速的进行DFS遍历。
核心就是BFS构图,DFS遍历。具体如下:
bfs构建最短路径的graph。(注意每一层的元素,不同的元素对应的下一个节点可能是相同的,当前层需要构建完graph之后再删除下一层的节点)。
dfs回溯获取最短路径的所有可能。(注意如果在开始和结束直接回溯,找到结果之后不能直接return,否则执行不到remove最后一个元素)。
var findLadders = function (beginWord, endWord, wordList) {
const wordSet = new Set(wordList);
wordSet.add(beginWord);
if (!wordSet.has(endWord)) return [];
const levelMap = new Map();
const wordMap = new Map();
const queue = [beginWord];
const visited = new Set();
let finished = false;
let level = 0;
levelMap.set(beginWord, 0);
visited.add(beginWord);
while (queue.length > 0) {
let levelSize = queue.length;
level++;
for (let i = 0; i < levelSize; i++) {
const word = queue.shift();
for (let j = 0; j < word.length; j++) {
for (let code = 97; code <= 122; code++) {
const newWord =
word.slice(0, j) + String.fromCharCode(code) + word.slice(j + 1);
if (!wordSet.has(newWord)) continue;
if (wordMap.has(newWord)) {
wordMap.get(newWord).push(word);
} else {
wordMap.set(newWord, [word]);
}
if (visited.has(newWord)) continue;
if (newWord === endWord) finished = true;
levelMap.set(newWord, level);
queue.push(newWord);
visited.add(newWord);
}
}
}
}
if (!finished) return [];
const res = [];
dfs(res, [], beginWord, endWord, wordMap, levelMap);
return res;
};
function dfs(res, path, beginWord, word, wordMap, levelMap) {
if (word === beginWord) {
res.push([beginWord, ...path]);
return;
}
path.unshift(word);
if (wordMap.get(word)) {
for (const parent of wordMap.get(word)) {
if (levelMap.get(parent) + 1 === levelMap.get(word)) {
dfs(res, path, beginWord, parent, wordMap, levelMap);
}
}
}
path.shift();
}
思考
注意点:只能说非常繁琐,BFS+DFS的结合,中间剪枝也挺麻烦的。这到题目可以说是名副其实的困难题。真的挺难。
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤