LeetCode 11.05每日一题 127. 单词接龙【中等】

单词接龙 

题目:

给定两个单词(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的方法。

原文地址:https://www.cnblogs.com/liangtao999/p/13934803.html