zoukankan      html  css  js  c++  java
  • leetcode每日一题(2020-06-07)126. 单词接龙 II

    题目描述:
    给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:

  • 每次转换只能改变一个字母。
  • 转换过程中的中间单词必须是字典中的单词。
  • 说明:
  • 如果不存在这样的转换序列,返回一个空列表。
  • 所有单词具有相同的长度。
  • 所有单词只由小写字母组成。
  • 字典中不存在重复的单词。
  • 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
  • ![](https://img2020.cnblogs.com/blog/1846400/202006/1846400-20200607164917897-151365496.png) ![](https://img2020.cnblogs.com/blog/1846400/202006/1846400-20200607164928327-1688308351.png)

    今日学习:
    1.最长公共前缀(这是另一道题):substr()
    2.BFS也好难啊


    最长公共前缀的题解
    题解1:

    var longestCommonPrefix = function(strs) {
        if(strs.length == 0) return ""
        if(strs.length == 1) return strs[0]
        let shortestChar = strs[0];//最短字符串
        let str = [...strs]
        for(char of str) {
            if(char.length <= shortestChar.length) {
                shortestChar = char
            }
        }
        let shortest = shortestChar.length
        let res = []
        let i = 0
        let count = 0
        while(i < shortest) {
            for(char of strs) {
                if(char[i] == shortestChar[i]) {
                    count++
                    if(count == strs.length) {
                        res.push(char[i])
                    }
                }else {
                    i = shortestChar
                }
            }
            i++
            count = 0
        }
        return res.join("")
    };
    

    题解2:

    var longestCommonPrefix = function(strs) {
        if(strs.length == 0) 
            return "";
        let ans = strs[0];
        for(let i =1;i<strs.length;i++) {
            let j=0;
            for(;j<ans.length && j < strs[i].length;j++) {
                if(ans[j] != strs[i][j])
                    break;
            }
            ans = ans.substr(0, j);
            if(ans === "")
                return ans;
        }
        return ans;
    };
    

    这是单词接龙的题解,真的好复杂,我的想法是从两头逼近直到有重复字符出现,但是我失败了 题解1: ```javascript var findLadders = function(beginWord, endWord, wordList) { if (!wordList.length || !wordList.includes(endWord)) return [] let arr = [] // 用来对应 id 和 word的 let map = {} // 用来对应 word 和 id 的 let id = 0 for(let i =0;i { // 用来判断两个单词之间是否可以一步完成修改 let step = 0 for(let i=0;i} return res

    };

    题解2:
    ```javascript
    var findLadders = function (beginWord, endWord, wordList) {
      const wordSet = new Set(wordList); // 将单词表存入Set,Set的查找是O(1)
      wordSet.add(beginWord) // 这个其实要不要都行
      if (!wordSet.has(endWord)) return []; // 如果单词表中没有endWord,则没有路径
    
      const levelMap = new Map() // 存放路径中的单词对应的level,即路径的深度
      const wordMap = new Map()  // 存放路径中的单词是从哪些单词变来的
      const queue = [beginWord]  // BFS需要维护一个队列,初始放入level0的beginWord
      const visited = new Set()  // 存放访问过的路径节点(单词),避免重复
    
      let finished = false; // 标识,true代表存在变到endWord的路径,至少存在
    
      let level = 0; // 路径的深度,初始化0
    
      levelMap.set(beginWord, 0); // 记录beginWord的level为0
      visited.add(beginWord) // 路径的起点就是beginWord,后面不能再出现它,存入visited
    
      while (queue.length) { // 队列空了,代表所有的节点都遍历完了
        let levelSize = queue.length // 当前level的单词个数
        level++ // 对一层层的单词进行遍历,level+1
        for (let i = 0; i < levelSize; i++) { // 将当前层的单词逐个出列,并逐个考察
          const word = queue.shift(); // 当前出列的单词
          for (let i = 0; i < word.length; i++) { // 遍历当前单词的所有字符
            for (let code = 97; code <= 122; code++) { // 将当前字符替换为26个字符,生成newWord逐个试
    
              const newWord = word.slice(0, i) + String.fromCharCode(code) + word.slice(i + 1)
              if (!wordSet.has(newWord)) continue // 如果不是单词表中的单词,continue
    
              if (wordMap.has(newWord)) { // 新单词如果已经存在于wordMap,有自己的数组
                wordMap.get(newWord).push(word) // 对应的数组推入它的“父word”,即出列的单词
              } else {                    // 新单词不存在于wordMap,初始化一个数组
                wordMap.set(newWord, [word]) // 并放入“父word”
              }
    
              if (visited.has(newWord)) continue // 这个新单词已经存在于路径中,避免重复走过
              if (newWord === endWord) finished = true // 遇到了endWord,说明至少存在去往endWord的路径
    
              levelMap.set(newWord, level) // 记录这个单词所处于的路径的深度
              queue.push(newWord) // 这个新单词是下一层的,不断让下一层的单词入列
              visited.add(newWord) // 这个新单词访问过了,记录一下
            }
          }
        }
      }
      if (!finished) return []; // 无法从beginWord到达endWord,返回一个[]
      const res = []; 
      dfs(res, [], beginWord, endWord, wordMap, levelMap); // dfs的入口
      return res;
    };
    function dfs(res, path, beginWord, word, wordMap, levelMap) {
      if (word === beginWord) { // dfs的出口,如果dfs传入的word,已经和beginWord相同
        res.push([beginWord, ...path]) // 将完整的路径推入res数组,别忘了加上beginWord
        return;                        // path在dfs中是引用传递,要深拷贝一下再推入res 
      }
      path.unshift(word) // 将当前单词加入到path数组的开头
      if (wordMap.get(word)) { // 当前单词对应的“邻居单词”们
        for (let parent of wordMap.get(word)) { // 遍历当前单词对应的“邻居单词”们
          if (levelMap.get(parent) + 1 === levelMap.get(word)) { // 找出其中满足层次要求
            dfs(res, path, beginWord, parent, wordMap, levelMap) // 即找出路径中它的“父单词”,递归dfs
          }
        }
      }
      path.shift() // 回溯,撤销选择,将path数组开头的单词弹出
    }
    
查看全文
  • 相关阅读:
    python的深拷贝和浅拷贝
    jquery的each循环
    python开发要求
    Python的进程和线程(二)——IO密集型任务
    Python的进程和线程(一)——计算密集型任务
    Python常用模块(一)--argparse模块
    Chrome Headless模式(二)——Python+selenium+headerless
    beyond compare 命令行批量比对图片
    Chrome Headless模式(一)
    python实现在mac笔记本上更换桌面背景
  • 原文地址:https://www.cnblogs.com/autumn-starrysky/p/13062438.html
  • Copyright © 2011-2022 走看看