「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」
大家好今天给大家分享下一道 LeetCode 困难度 的题目126. 单词接龙 II
题目
按字典 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] 的形式返回。
(转载leetcode)
分析
分析
1.单词之间只能有一个字母不一样
2.替换后的单词必须在wordList中
3.返回一个二维数组
解法
1.DFS+BFS
解法:DFS+BFS
思路
1.这种当字符上的转化类似于一个字母的图谱, 每次转化都相当于一个可以来往返重复的单词图谱
2.在求图谱的时候我们需要做2件事
1.记录放过过的节点visited 防止重复访问
2.通过DFS一次访问这个图谱
3.在这题中,首先我们创建2个map
1.levelMap记录从开始beginword 到 endWord的层次的图谱, beginWord为第0层,endWord为最后层
2.wordMap 记录周边相邻的图谱,使用这个map记录周边相邻一个字母的单词
4.有了这2个map后,我们就可以通过BFS 的方式,从beginWord开始通过相邻图谱访问相邻节点,
再通过levelMap来求得中间的层次相差一层的节点,最后求得答案
*/
const findLadders = (beginWord, endWord, wordList) => {
// 创建一个单词库,并且把beginWord也加入其中
const wordSet = new Set(wordList);
wordSet.add(beginWord);
// 判断特殊的条件
if (!wordSet.has(endWord)) return [];
const levelMap = new Map(); // 记录层次的图谱
const wordMap = new Map(); // 记录周边相邻的图谱
const visited = new Set(); // 记录访问过的单词
visited.add(beginWord); // 必须加这个,不然hit 对应的level 是1
// 设置的一个变量finish 判断能否找到从beginword到endword的路径
let finished = false; // 能否完成
// beginWord为第0层
levelMap.set(beginWord, 0);
// 开始采用dfs的方式访问节点,形成levelMap 和 wordMap
function dfs(
beginWordArr,
endWord,
wordSet,
wordMap,
levelMap,
visited,
level
) {
if (!beginWordArr.length) return;
const next = [];
for (const word of beginWordArr) {
for (let i = 0; i < word.length; i++) {
for (let c = 97; c <= 122; c++) {
const newWord =
word.slice(0, i) + String.fromCharCode(c) + word.slice(i + 1);
if (!wordSet.has(newWord)) continue;
// 建立相邻单词图谱 只要能变成newWord都是它的邻居
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);
next.push(newWord);
visited.add(newWord);
}
}
}
dfs(next, endWord, wordSet, wordMap, levelMap, visited, level + 1);
}
dfs([beginWord], endWord, wordSet, wordMap, levelMap, visited, 1);
// 判断是否能找到路径,如果不能 则直接返回[]
if (!finished) return [];
/* 通过BFS 的方式,从beginWord开始通过相邻图谱访问相邻节点,
再通过levelMap来求得中间的层次相差一层的节点*/
const res = [];
const queue = [{ path: [], beginWord, endWord }];
while (queue.length) {
const { path, beginWord, endWord } = queue.shift();
// 当beginWord === endWord说明已经访问到了开始的节点
if (beginWord === endWord) {
res.push([beginWord, ...path]);
}
if (wordMap.get(endWord)) {
for (const parent of wordMap.get(endWord)) {
// 只用parent的层次=== endword的层次+1才能算最短路径
if (levelMap.get(parent) + 1 === levelMap.get(endWord)) {
// 采取逆向访问的方式 来从endWord访问到beginWord
queue.push({ path: [endWord, ...path], beginWord, endWord: parent });
}
}
}
}
return res;
};
总结
今天这道题是主要是练习使用DFS和BFS来求解"单词接龙II", 这道题比较复杂,属于graph类的题目,注意考察的是最图谱的建立,和如果使用图谱求得满足条件的元素
大家可以看看我分享的一个专栏(前端搞算法)里面有更多关于算法的题目的分享,希望能够帮到大家,我会尽量保持每天晚上更新,如果喜欢的麻烦帮我点个赞,十分感谢
大家如果对“TS”感兴趣的可以看看我的专栏 (TypeScript常用知识),感谢大家的支持
文章内容目的在于学习讨论与分享学习算法过程中的心得体会,文中部分素材来源网络,如有侵权,请联系删除,邮箱 182450609@qq.com
\