使用条件检查切换过程,而不是在wordLadder中交换

时间:2019-04-04 04:15:40

标签: python

我模仿leetcode中wordLadder问题的双向解决方案 Word Ladder - LeetCode

  

给出两个单词( beginWord endWord ),以及字典的单词列表,找到从 beginWord 的最短转换序列的长度。 em> endWord ,例如:

     
      
  1. 一次只能更改一个字母。
  2.   
  3. 每个转换的单词都必须存在于单词列表中。请注意, beginWord 不是 转换后的单词。
  4.   
     

注意:

     
      
  • 如果没有这样的转换序列,则返回0。
  •   
  • 所有单词的长度相同。
  •   
  • 所有单词仅包含小写字母字符。
  •   
  • 您可以假定单词列表中没有重复项。
  •   
  • 您可能认为 beginWord endWord 是非空的并且不相同。
  •   
     

示例1:

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

Output: 5

Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.
     

示例2:

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

Output: 0

Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.

解决方案

class Solution2(object):
    def ladderLength(self, beginWord, endWord, wordList):
        #base case
        if (endWord not in wordList) or (not endWord) or (not beginWord) or (not wordList):
            return 0
        size = len(beginWord)
        word_set = set(wordList)    
        forwards, backwards = {beginWord}, {endWord}
        visited = set()
        step = 0
        while forwards and backwards:
            step += 1 #treat the first word as step 1
            if len(forwards) > len(backwards): 
                forwards, backwards = backwards, forwards #switch process
            #logging.debug(f"step: {step}, forwards: {forwards}, backwords: {backwards}")

            neighbors= set()   
            for word in forwards:#visit words on this level
                if word in visited: continue

                for i in range(size):
                    for c in 'abcdefghijklmnopqrstuvwxyz':
                        next_word = word[:i] + c + word[i+1:]
                        if next_word in backwards: return step +  1 #terminating case
                        if next_word in word_set: neighbors.add(next_word)
                        #logging.debug(f"next_word{next_word}, step: {step}")
                visited.add(word) #add visited word as the final step 
            forwards = neighbors 
        #logging.debug(f"final: {step}")
        return 0

enter image description here

切换过程参考

        if len(forwards) > len(backwards): 
            forwards, backwards = backwards, forwards #switch process

此解决方案简洁但不直观,我尝试将其更改为

if len(forwards) <= len(backward): current = forwards
else: current = backwards
neighbors = set()
for word in current:
 .......

很遗憾,最后一步forwards = neighbors无法正确处理。

如何解决问题

1 个答案:

答案 0 :(得分:1)

这称为bidirectional search算法。此解决方案中的forwardbackward是一种two-pointer的想法,请始终选择较大的集合来进行BFS。它有助于更​​快地找到路径。

关于您要使用current而不是切换forwardbackward的问题,我认为这是不可能的。原因是,我们在逻辑中同时使用了forwardbackward,因此在current之外,您还应该提供类似another的变量。但是currentanotherforwardbackward相同,因此您的想法行不通。

我认为该two-pointer版本足够优雅简洁,我个人喜欢它。

我想出另一种方法,使用current index接近您的想法:

class Solution:
    def ladderLength(self, beginWord, endWord, wordList):
        #base case
        if (endWord not in wordList) or (not endWord) or (not beginWord) or (not wordList):
            return 0
        size = len(beginWord)
        word_set = set(wordList)    
        entries = [{beginWord}, {endWord}]
        visited = set()
        step = 0
        cur = 0
        while entries[cur] and entries[1-cur]:
            step += 1 #treat the first word as step 1
            if entries[1-cur] > entries[cur]: #switch process
                cur ^= 1

            neighbors= set()   
            for word in entries[cur]:#visit words on this level
                if word in visited: continue

                for i in range(size):
                    for c in 'abcdefghijklmnopqrstuvwxyz':
                        next_word = word[:i] + c + word[i+1:]
                        if next_word in entries[1-cur]: return step +  1 #terminating case
                        if next_word in word_set: neighbors.add(next_word)

                visited.add(word) #add visited word as the final step 
            entries[cur] = neighbors 
        return 0

希望对您有所帮助,如果还有其他问题,请发表评论。 :)