LeetCode算法学习之--DFS&&BFS--*126. 单词接龙 II*

293 阅读2分钟

「这是我参与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] 的形式返回。

image.png (转载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

\