zoukankan      html  css  js  c++  java
  • 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.

  • 相关阅读:
    PDO 数据访问抽象层
    注册审核、批量删除
    分页查询
    会话用法
    封装成类
    多条件查询(复选框条件)
    IP子网划分
    redhat 用yum安装的apache、mysql一般默认安装在哪个目录下?
    nslookup
    linux 设置时间
  • 原文地址:https://www.cnblogs.com/xingguozhiming/p/10909234.html
Copyright © 2011-2022 走看看