LeetCode题解:127. 单词接龙,双向BFS,JavaScript,详细注释

原题链接:https://leetcode-cn.com/problems/word-ladder/

解题思路:

  1. 分别以beginWord和endWord为起点,分别向中间推进,当两者相遇时,即为找到了最短路径。
  2. 每次推进都选取两端队列中较小者,能够优化遍历的次数。
  3. BFS需要使用队列,当一端队列元素的下一个变化单词存在于另一端的队列中时,即可认为两者相遇。
  4. 使用Map判断单词是否存在于队列中,可以进一步优化速度。因此可以在每次遍历队列前,都将另一端的队列转换为Map。
  5. 需要注意的测试用例:
"ymain"
"oecij"
["ymann","yycrj","oecij","ymcnj","yzcrj","yycij","xecij","yecij","ymanj","yzcnj","ymain"]
/**
 * @param {string} beginWord
 * @param {string} endWord
 * @param {string[]} wordList
 * @return {number}
 */
var ladderLength = function (beginWord, endWord, wordList) {
  // 每次都遍历队列,初始时存入beginWord,对应层级为1
  let queue = [[beginWord, 1]];
  // 虽然两端的遍历都需要使用队列,实际操作时可以用Map来加速判断是否相遇的过程
  // 每次遍历时,只需要取queue和map中长度较小的一个,将其转换为一个队列进行遍历即可
  let map = new Map([[endWord, 1]]);
  // 使用Set判断wordList中的单词是否被使用过
  let wordSet = new Set(wordList);

  // 由于双向BFS即使endWord不存在于wordList中,也有可能会相遇
  // 因此要先判断wordList中是否有endWord,若不存在则表示无法转换
  if (!wordSet.has(endWord)) {
    return 0;
  }

  // 如果queue和map中任意一个被清空,表示双向BFS不会相遇,即为无法进行转换
  while (queue.length && map.size) {
    // 选取queue和map中较短的一个进行遍历,优化搜索速度
    if (queue.length > map.size) {
      // 将queue和map对调,保证每次遍历的都是queue
      [queue, map] = [Array.from(map), new Map(queue)];
    }

    // 将queue中元素出队,搜索下一个转换的单词
    const [word, level] = queue.shift();

    // 遍历当前单词的每个字符
    for (let i = 0; i < word.length; i++) {
      // 生成a-z的字符
      for (let j = 97; j < 123; j++) {
        // 以单词hit为例,此处生成的是该单词中每个字母所有可能变化情况
        // 即为*it、h*t、hi*,*号可被a-z替代
        const newWord =
          word.slice(0, i) + String.fromCharCode(j) + word.slice(i + 1);

        // 如果newWord在map中存在,表示双向BFS相遇,即为找到了最短序列
        if (map.has(newWord)) {
          // 将两端的level想加,即为总长度
          return map.get(newWord) + level;
        }

        // 如果newWord存在于wordList中,表示newWord可作为下一个转换单词
        if (wordSet.has(newWord)) {
          // 将newWord从wordList中删除,避免重复使用
          wordSet.delete(newWord);
          // 将newWord入队,进行下一层搜索,同时层级加一
          queue.push([newWord, level + 1]);
        }
      }
    }
  }

  // 如果推出循环,表示未找到转换序列,返回0
  return 0;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值