daily_leetcode_2020_1105_127_单词接龙


1 题目描述

给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:

每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:

如果不存在这样的转换序列,返回 0。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。

输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

输出: 5

解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",
     返回它的长度 5。


输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

输出: 0

解释: endWord "cog" 不在字典中,所以无法进行转换。

2 题解

简单来说就是求图的两点最短路径,每个单词看成一个点,只有相差一个字符的点之间才有路径,路径权值全部为1.

2.1 BFS

广度优先搜素是最直观的,但是这个超时了。。。

class Solution:

    def ladder_length(self, beginWord: str, endWord: str, wordList: [str]) -> int:

        from queue import Queue
        queue = Queue()
        wordList_len = len(wordList)
        word_len = len(beginWord)

        """ 用来标记wordList中的元素是否遍历过 """
        flag = [1 for i in range(wordList_len)]

        res = 1
        queue.put(beginWord)

        def can_change(str1, str2):
            """

            判断 str1 和 str2 是否 对应位置只有一位不相等
            :param str1:
            :param str2:
            :return:
            """
            return sum(1 if str1[i] != str2[i] else 0 for i in range(word_len)) == 1



        while queue.not_empty:

            res += 1
            size = queue.qsize()

            while size > 0:
                head_str = queue.get()

                for i in range(wordList_len):
                    """ 该元素已经遍历过, 跳过 """
                    if flag[i] == 0:
                        continue

                    val = wordList[i]
                    """ 是联通的 """
                    if can_change(head_str, val):
                        if val == endWord:
                            return res
                        queue.put(val)
                        flag[i] = 0
                size -= 1

        return 0

    def main(self):
        # beginWord = "b"
        # endWord = "e"
        # wordList = ["a","e"]

        beginWord = "teach"
        endWord = "place"
        wordList = ["peale", "wilts", "place", "fetch", "purer", "pooch", "peace", "poach", "berra", "teach", "rheum",
                    "peach"]

        print(self.ladder_length(beginWord, endWord, wordList))


if __name__ == '__main__':
    solution = Solution()
    solution.main()

2.2 暴力

别人的一种解法 作者此题评论区 habbi

思路:每次拿到一个节点时生成所有可能的下一个节点(可联通的),新生成的节点只要再列表中就参与计算

class Solution:
    def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:

        if endWord not in wordList:
            return 0

        l = len(endWord)


        ws = set(wordList)

        head = {beginWord}
        tail = {endWord}
        tmp = list('abcdefghijklmnopqrstuvwxyz')
        res = 1
        while head:
            if len(head) > len(tail):
                head, tail = tail, head

            q = set()
            for cur in head:
                for i in range(l):
                    for j in tmp:
                        word = cur[:i] + j + cur[i+1:]

                        if word in tail:
                            return res + 1

                        if word in ws:
                            q.add(word)
                            ws.remove(word)
            head = q
            res += 1


        return 0

3 总结


作者: jdi146
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 jdi146 !
评论
评论
  目录