126. Word Ladder II(js)

Posted xingguozhiming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了126. Word Ladder II(js)相关的知识,希望对你有一定的参考价值。

126. Word Ladder II

Given two words (beginWord and endWord), and a dictionary‘s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:

  1. Only one letter can be changed at a time
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

Note:

  • Return an empty list if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

Example 1:

Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

Output:
[
  ["hit","hot","dot","dog","cog"],
  ["hit","hot","lot","log","cog"]
]

Example 2:

Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

Output: []

Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
题意:给出开始单词和结束单词,从单词列表中找出单词使得从开始单词到结束单词形成接龙,每次只允许替换一个字符,求出所有情况
代码如下:
‘use strict‘;
var findLadders = function(start, end, dict) {
  // 常量
  var A_CODE = ‘a‘.charCodeAt(0);
  var WORD_COUNTS = 26;
  var wordLength = start.length;
  var results;
  var currents, next;
  var isFounded = false;
  var dictSet = new Set(dict);

  // 判断一次字符转换是否有效
  var isValid = function(from, to) {
    var i = 0, c = 0;
    while (i < wordLength) {
      if (from.charCodeAt(i) !== to.charCodeAt(i)) {
        ++c;
      }
      ++i;
    }

    return (c === 1);
  };

  // 字符替换
  var replacedWord = function(word, idx, chCode) {
    var newStr = 
      word.substr(0, idx) + String.fromCharCode(chCode) + word.substr(idx + 1);
    return newStr;
  };

  // If its only one step from start to end.
  if (start === end || isValid(start, end)) {
    return [[start, end]];
  } else if (!dictSet.has(end)) {
    return [];
  }

  results = [];
  var startSet = new Set([start]);
  var endSet = new Set([end]);
  var startPath = [[start]];
  var endPath = [[end]]
  

  var isReversing = false;
  var isConnected = false;

  // Use to decide whether use all word possible or use all dice word.
  var wordCombinations = WORD_COUNTS * wordLength;
  var dictComputations;

  // Determine current paths.
  var currentPaths;
  var currentLength;
  var currentSet;
  var pathLength;


  var nextPaths;


  var currentPath, currentWord, targets, target, tmpPath;


  var i, j, k;

  // 初始化
  currentPaths = startPath;
  currentSet = startSet;
  currentLength = currentPaths.length;
  
  while (currentLength > 0) {
    nextPaths = [];
    // 从currentSet中删除key
    targets = currentSet.keys();
    for (target of targets) {
      dictSet.delete(target);
    }
    currentSet.clear();
    dictComputations = dictSet.size * wordLength;
    // Decide whether to use dict iteration of word replaces.
    if (dictComputations < wordCombinations) {
      // If iteration though dict needs less compares, iterate it.
      for (i = 0; i < currentLength; ++i) {
        currentPath = currentPaths[i];
        currentWord = currentPath[currentPath.length - 1];
        targets = dictSet.keys();
        for (target of targets) {
          if (isValid(currentWord, target)) {
            tmpPath = currentPath.slice();
            tmpPath.push(target);
            nextPaths.push(tmpPath);
            currentSet.add(target);
          }
        }
      }
    } else {
      
      for (i = 0; i < currentLength; ++i) {
        currentPath = currentPaths[i];
        currentWord = currentPath[currentPath.length - 1];
        for (j = 0; j < wordLength; ++j) {
          for (k = 0; k < WORD_COUNTS; ++k) {
            target = replacedWord(currentWord, j, A_CODE + k);
            if (dictSet.has(target)) {
              tmpPath = currentPath.slice();
              tmpPath.push(target);
              nextPaths.push(tmpPath);
              currentSet.add(target);
            }
          }
        }
      }
    }
    if (isReversing) {
      endPath = nextPaths;
    } else {
      startPath = nextPaths;
    }

    if (startSet.size > endSet.size) {
      targets = endSet.keys();
      currentSet = startSet;
    } else {
      targets = startSet.keys();
      currentSet = endSet;
    }

    for (target of targets) {
      if (currentSet.has(target)) {
        isConnected = true;
        break;
      }
    }
    if (isConnected) {
      break;
    } else {
      // 取小
      isReversing = startPath.length > endPath.length ? true : false;
      currentSet = isReversing ? endSet : startSet;
      currentPaths = isReversing ? endPath : startPath;
      currentLength = currentPaths.length;
    }
  }

  
  if (isConnected) {
    currentLength = startPath.length;
    pathLength = endPath.length;
    // Reverse endPaths.
    for (j = 0; j < pathLength; ++j) {
      endPath[j].reverse();
    }
    for (i = 0; i < currentLength; ++i) {
      currentPath = startPath[i];
      currentWord = currentPath[currentPath.length - 1];
      if (!endSet.has(currentWord)) {
        continue;
      }
      for (j = 0; j < pathLength; ++j) {
        target = endPath[j];
        if (currentWord === target[0]) {
          tmpPath = currentPath.concat(target.slice(1));
          results.push(tmpPath);
        }
      }
    }
  }
  return results;
};

参考链接:https://leetcode.com/problems/word-ladder-ii/discuss/40606/Share-my-javascript-solution-with-2-way-BFS-cost-about-250ms.

以上是关于126. Word Ladder II(js)的主要内容,如果未能解决你的问题,请参考以下文章

126. Word Ladder II

126. Word Ladder II

126 Word Ladder II

126. Word Ladder II

python 126. Word Ladder II(Slack01).py

python 126. Word Ladder II(Slack01).py