LeetCode題解:127. 單詞接龍,雙向BFS,JavaScript,詳細註釋

Lee_Chen86發表於2020-12-18

原題連結: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;
};

相關文章