【前端刷题】127.单词接龙(HARD)

155 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

题目(Word Ladder)

链接:https://leetcode-cn.com/problems/word-ladder
解决数:764
通过率:47.4%
标签:广度优先搜索 哈希表 字符串 
相关公司:amazon facebook google 

字典 wordList 中从单词 beginWord **和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk

  • 每一对相邻的单词只差一个字母。
  •  对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意, beginWord **不需要在 wordList 中。
  • sk == endWord

给你两个单词 **beginWord **和 endWord 和一个字典 wordList ,返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0 。

 

示例 1:

输入: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出: 5
解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5

示例 2:

输入: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出: 0
解释: endWord "cog" 不在字典中,所以无法进行转换。

 

提示:

  • 1 <= beginWord.length <= 10
  • endWord.length == beginWord.length
  • 1 <= wordList.length <= 5000
  • wordList[i].length == beginWord.length
  • beginWordendWord 和 wordList[i] 由小写英文字母组成
  • beginWord != endWord
  • wordList 中的所有字符串 互不相同

思路

bfs,循环beginWord,对每个字符替换26个小写字符,看新生成的单词是否在wordList里面,如果存在就是一个合法的路径,直到新生成的单词是endWord,循环完成还是没到达endWord就返回0。双向bfs思路一样,只不过是从两边向中间靠拢,判断新生成的单词是否在另一个方向走过的路径中。

方法1:bfs

js:

const ladderLength = (beginWord, endWord, wordList) => {
  const wordSet = new Set(wordList);
  const queue = [];
  queue.push([beginWord, 1]);//开始单词和层级加入队列

  while (queue.length) {
    const [word, level] = queue.shift()//出队 进行bfs
    if (word == endWord) {//和endword相等返回层级
      return level;
    }
    for (let i = 0; i < word.length; i++) { //循环单词列表
      for (let c = 97; c <= 122; c++) { //循环26个小写字符
        //得到新的单词
        const newWord = word.slice(0, i) + String.fromCharCode(c) + word.slice(i + 1);
        if (wordSet.has(newWord)) { //检查wordset包不包括新生成的单词 避重复入列
          queue.push([newWord, level + 1]); //新单词加入队列
          wordSet.delete(newWord);  //避死循环
        }
      }
    }
  }
  return 0; // bfs结束,始终没有遇到终点
};
方法2:双向bfs

js:

var ladderLength = function(beginWord, endWord, wordList) {
    let wordSet = new Set(wordList)
    if (!wordSet.has(endWord)) return 0
    //从beginWord到endWord
    let begSet = []
		//从endWord到beginWord
    let endSet = []
    begSet.push(beginWord)
    endSet.push(endWord)

    let n = 1//层级
    while(begSet.length > 0){//开始遍历单词
        const nextBegins = []//bfs下一层级的单词数组
        //步数少数对换一下,让走的慢的在走几步
        if(begSet.length > endSet.length){
            let q = begSet
            begSet = endSet
            endSet = q
        }
        //循环begSet
        for(let k = 0; k < begSet.length;k++){
            let m = begSet[k]
            for(let i = 0; i < m.length; i++){
                for (let c = 97; c <= 122; c++){
                    //生成新词
                    let newm = m.slice(0, i) + String.fromCharCode(c) + m.slice(i + 1);
                    if(endSet.includes(newm)){//相遇
                        return n + 1
                    }
                    if( wordSet.has(newm)){
                        nextBegins.push(newm)	//下一层bfs的单词数组
                        wordSet.delete(newm)  //防止重复
                    } 
                }
            }
        }
        begSet = nextBegins
        n++ //层级+1
    }
    return 0
   
};