leetcode 127. Word Ladder(python)

623 阅读3分钟

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金

描述

A transformation sequence from word beginWord to word endWord using a dictionary wordList is a sequence of words beginWord -> s1 -> s2 -> ... -> sk such that:

  • Every adjacent pair of words differs by a single letter.
  • Every si for 1 <= i <= k is in wordList. Note that beginWord does not need to be in wordList.
  • sk == endWord

Given two words, beginWord and endWord, and a dictionary wordList, return the number of words in the shortest transformation sequence from beginWord to endWord, or 0 if no such sequence exists.

Example 1:

Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
Output: 5
Explanation: One shortest transformation sequence is "hit" -> "hot" -> "dot" -> "dog" -> cog", which is 5 words long.

Example 2:

Input: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
Output: 0
Explanation: The endWord "cog" is not in wordList, therefore there is no valid transformation sequence.

Note:

1 <= beginWord.length <= 10
endWord.length == beginWord.length
1 <= wordList.length <= 5000
wordList[i].length == beginWord.length
beginWord, endWord, and wordList[i] consist of lowercase English letters.
beginWord != endWord
All the words in wordList are unique.

解析

根据题意,就是给出了一个 beginWord ,经过在 wordList 中一系列的查找,最后能得到 endWord 的单词序列长度,这里的查找要求每次只能变化一个字母。其实这个题就是类似于走迷宫,只不过每次变化的可能从 4 个变成了 26 个。这里我用集合 visited 来存储已经用过的单词,然后利用栈变量 queue 保存查找到的有效的单词,再对栈中的每个单词进行进一步深入的变化和查找,将可能的单词再追加入栈中,直到找到 endWord 为止,并返回这个寻找过程中产生的变化序列的距离。

不知道为何会超时,尴了个尬。这种方法可能还是存在缺陷吧,也可能是题目的限制比较大,可以换一种思路继续进行解题。

解答

class Solution(object):
    def ladderLength(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: int
        """
        queue = [(beginWord, 1)]
        visited = set()

        while queue:
            word, dist = queue.pop(0)
            if word == endWord:
                return dist
            for i in range(len(word)):
                for j in 'abcdefghijklmnopqrstuvwxyz':
                    tmp = word[:i] + j + word[i+1:]
                    if tmp not in visited and tmp in wordList:
                        queue.append((tmp, dist+1))
                        visited.add(tmp)
        return 0
        	      
		

运行结果

Time Limit Exceeded

解析

换一种思路,很多时间都浪费在了制造出来的 tmp 判断是否已经用过并且是否存在于 wordList 种,我们可以缩减这一部分的时间,如果这个制造出来的单词出现在 wordList ,说明就会一定用到它,所以不需要记录在 visited ,直接将其从 wordList 删除即可,这样可以减少布尔语句的判断时间,并且随着查找的进行不断删减单词, wordList 残留会越来越少,也会同时减少查找的时间。这次没有超时,但是耗时还是很多。

解答

class Solution(object):
    def ladderLength(self, beginWord, endWord, wordList):
        """
        :type beginWord: str
        :type endWord: str
        :type wordList: List[str]
        :rtype: int
        """
        wordList = set(wordList)
        queue = [(beginWord, 1)]
        for word, dist in queue:
            if word == endWord:
                return dist
            for i in range(len(word)):
                for char in 'abcdefghijklmnopqrstuvwxyz':
                    tmp = word[:i] + char + word[i + 1:]
                    if tmp in wordList:
                        queue.append([tmp, dist + 1])
                        wordList.remove(tmp)
        return 0

运行结果

Runtime: 513 ms, faster than 25.82% of Python online submissions for Word Ladder.
Memory Usage: 14.6 MB, less than 62.38% of Python online submissions for Word Ladder.

原题链接:leetcode.com/problems/wo…

您的支持是我最大的动力