LeetCode127-单词接龙

听身边的一些朋友说

今年的工作不好找

尤其是算法岗

要求都是要发论文或者是打算法比赛

深深地为自己担心

于是赶紧找到一博士生师兄

希望他来辅导自己写论文

嗯,对

我程某人暑假要开始写论文啦


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" 不在字典中,所以无法进行转换。

思路:

这一题是比较典型的广度遍历问题,题目要求是找到从 beginWord 到 endWord 的最短转换序列的长度,就拿示例一来说,如下图所示:

其实就是将beginWord 单词作为树的根节点,依次向下遍历,看这棵树的叶子结点有没有endWord (有时候也不一定是叶子结点)。如果存在,返回其深度depth,反之返回0。此处有一点需要注意:

在树上层出现过的字符串没必要在下层再次出现,因为如果该字符串是转换过程中必须经过的中间字符串,那么应该挑选上层的该字符串继续进行变化,它的转换次数少。

因为题目所求的是最短转换序列的长度,所以一定要记住这一点。

另外还有一点就是这个转换规则:每次转换只能改变一个字母。每一次迭代中如何来找当前单词的转换单词呢?这里面所用的方法有很多种,我看了网上的一些帖子,大致分为两种。一种是将改变的字母按照小写字母排列情况分为26种情况,依次填进去进行判断。另一种是将改变字母的那个位置用“_”代替,比如“hit”要改变第二个位置的字母,则可表示为“h_t”,而“hot”改变第二个位置的字母后也可表示为“h_t”,说明这两个单词是可以直接转换的。

下面我将依次给出这两种方法的代码。

方法一代码如下:

class Solution(object):
    # 本题采用广度遍历方法
    def ladderLength(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: int
        """
        # 首先给wordList列表中单词去重
        word_set = set(wordList)
        # 定义当前层的单词集合为beginWord
        cur_word = [beginWord]
        # 定义下一层的单词集合
        next_word = []
        # 定义从 beginWord 到 endWord 的最短转换序列的长度
        depth = 1
        while cur_word:
            for word in cur_word:
                # 如果endWord出现在当前层的cur_word单词集合中,则立即返回该深度
                if word == endWord:
                    return depth
                for index in range(len(word)):
                    for indice in "abcdefghijklmnopqrstuvwxyz":
                        new_word = word[:index]+indice+word[index+1:]
                        if new_word in word_set:
                            word_set.remove(new_word)
                            next_word.append(new_word)
            # 如果endWord未出现在当前层的cur_word单词集合中,则深度+1
            depth += 1
            cur_word = next_word
            next_word = []
        return 0

if __name__ == "__main__":
    beginWord = "hit"
    endWord = "cog"
    wordList = ["hot","dot","dog","lot","log","cog"]
    sequence_length = Solution().ladderLength(beginWord, endWord, wordList)
    print(sequence_length)

执行效率很一般,在30%左右。

方法二代码如下:

class Solution(object):
    # 本题采用广度遍历方法
    def ladderLength(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: int
        """
        # 首先给wordList列表中单词去重
        word_set = set(wordList)
        word_dict = {}
        for word in word_set:
            for index in range(len(word)):
                new_word = word[:index]+"_"+word[index+1:]
                if new_word not in word_dict.keys():
                    word_dict[new_word] = [word]
                else:
                    word_dict[new_word].append(word)
        # 定义当前层的单词集合为beginWord
        cur_word = [beginWord]
        # 定义下一层的单词集合
        next_word = []
        # 定义从 beginWord 到 endWord 的最短转换序列的长度
        depth = 1
        while cur_word:
            for word in cur_word:
                # 如果endWord出现在当前层的cur_word单词集合中,则立即返回该深度
                if word == endWord:
                    return depth
                for index in range(len(word)):
                    new_word = word[:index]+"_"+word[index+1:]
                    if new_word in word_dict.keys():
                        for w in word_dict[new_word]:
                            if w not in next_word:
                                next_word.append(w)
                        del word_dict[new_word]
            # 如果endWord未出现在当前层的cur_word单词集合中,则深度+1
            depth += 1
            cur_word = next_word
            next_word = []
        return 0

if __name__ == "__main__":
    beginWord = "hit"
    endWord = "cog"
    wordList = ["hot","dot","dog","lot","log","cog"]
    sequence_length = Solution().ladderLength(beginWord, endWord, wordList)
    print(sequence_length)

但此种方法超出时间限制了,这让我有些费解,因为我始终觉得此方法迭代的次数会更少,效率自然也会更快。各位读者如果看出了我的错误,还望积极留言指出啊。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习的学习者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值