题目:
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:
如果不存在这样的转换序列,返回 0。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例 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" 不在字典中,所以无法进行转换。
如果不了解bfs,本题相当难度的,搜索最短路径,需要用到广度优先遍历的思想,bfs和dfs的理解可以参考
思路:
从起点词出发,每次变动一个字母,经过 n 次变换,变成终点词,希望 n 尽量小。
找出邻接关系,比如hit它变一个字母会变成_it、h_t、hi_形式的单词。
然后看这个新词是否存在于单词表,如果存在,就找到了一个下一层的转换词。
同时,要避免重复访问,比如hit->hot->hit这样变回来,只会徒增转换的长度。
因此,要将下一个转换词从单词表中删除(单词表的单词是唯一的)。
/** * @param {string} beginWord * @param {string} endWord * @param {string[]} wordList * @return {number} */ var ladderLength = function(beginWord, endWord, wordList) { var queue=[]; var wordset=new Set(wordList); var s="abcdefghijklmnopqrstuvwxyz" queue.push([beginWord, 1]); while(queue.length){ var [word,level]=queue.shift(); if(word==endWord){ return level; } for(var i=0;i<word.length;i++){ for(var j=0;j<s.length;j++){ var temp=word.substring(0,i)+s[j]+word.substring(i+1); if(wordset.has(temp)){ queue.push([temp, level+1]); wordset.delete(temp); } } } } return 0; };
还有另外一个思路:不从单词表中去匹配,而是使用issimilar方法去比较两个单词是否差1。
/** * @param {string} beginWord * @param {string} endWord * @param {string[]} wordList * @return {number} */ var ladderLength = function(beginWord, endWord, wordList) { var queue=[];//维护一个队列 queue.push([beginWord, 1]); var issimilar=function(f,s){//判断两数差一位 var count=0; for(var i=0;i<f.length;i++){ if(f[i]!=s[i]){ count++; if(count>=2) return false; //加了判断,运行时间少了250ms } } return count==1; } while(queue.length){//BFS 广度优先搜索 var [word,level]=queue.shift(); if(word==endWord){//当出列的单词和终点词相同,说明遇到了终点词,返回它的 level。 return level; } for(var i=0;i<wordList.length;i++){ if(issimilar(word,wordList[i])){//判断两数是否差一 queue.push([wordList[i], level+1]);//将它入列,它的 level+1,并从单词表中删去这个词。 wordList.splice(i,1); //相较于delete wordList[i] 运行时间少了200ms i--; } } } return 0;//没有遇到终点词,没有路径通往终点,返回 0。 };
运行结果内存消耗大大减少,主要减少了wordset这块。耗时增加了,主要是比较差1的方法。