详尽地获得三个字母组成的单词的所有可能组合

时间:2019-04-03 09:38:36

标签: python

我正在研究leetcode问题“ wordLadder”

  

给出两个单词( 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 Solution:
    def ladderLength(self, beginWord, endWord, wordList):
        visited = set()
        wordSet = set(wordList)

        queue = [(beginWord, 1)]

        while len(queue) > 0:
            word, step = queue.pop(0)
            logging.debug(f"word: {word}, step:{step}")

            #base case 
            if word == endWord:
                return step #get the result.
            if word in visited: #better than multiple conditions later.
                continue

            for i in range(len(word)):
                for j in range(0, 26): 
                    ordinal = ord('a') + j
                    next_word = word[0:i] + chr(ordinal) + word[i + 1:]
                    logging.debug(f"changed_word: {next_word}")
                    if next_word in wordSet: 
                        queue.append((next_word, step + 1))
            visited.add(word) # paint word as visited

        return 0 

要用尽所有可能的单词组合

enter image description here

我阅读了讨论区,全部采用了切片技术

next_word = word[0:i] + chr(ordinal) + word[i + 1:]

还有其他解决方案可以解决该问题吗?

2 个答案:

答案 0 :(得分:1)

这是一个经典的网络问题。您应该做的是生成一个平方矩阵,其尺寸等于词典中单词的数量。然后用单词填充矩阵,只要单词是彼此相对的一个字母转换即可。 network['hot']['not'] = 1所有其他单元格都必须为0。 现在,您定义了网络,可以使用最短路径算法(例如Dijkstra)来解决问题

答案 1 :(得分:1)

您可以使用levenshtein距离(信用:This Answer)作为度量标准来了解确切的距离。在Wikipedia页面上:

Levenshtein距离是用于测量 两个序列之间的差异。非正式地讲,Levenshtein距离 两个单词之间是单字符编辑的最小数量 (插入,删除或替换)更改一个单词所需的信息 进入另一个。

如下:

def levenshteinDistance(s1, s2):
    if len(s1) > len(s2):
        s1, s2 = s2, s1

    distances = range(len(s1) + 1)
    for i2, c2 in enumerate(s2):
        distances_ = [i2+1]
        for i1, c1 in enumerate(s1):
            if c1 == c2:
                distances_.append(distances[i1])
            else:
                distances_.append(1 + min((distances[i1], distances[i1 + 1], distances_[-1])))
        distances = distances_
    return distances[-1]

然后,您可以简单地使用levenshtein距离来筛选出彼此相距一个字符的对,例如:

new_list= []
mylist =  [beginWord].__add__(wordList)
for idx1, elem1 in enumerate(mylist):
    for idx2, elem2 in enumerate(mylist):
        if levenshteinDistance(elem1,elem2) == 1 and idx1 < idx2:
            new_list.append((elem1,elem2))
            
new_list

哪个输出:

[('hit', 'hot'),
 ('hot', 'dot'),
 ('hot', 'lot'),
 ('dot', 'dog'),
 ('dot', 'lot'),
 ('dog', 'log'),
 ('dog', 'cog'),
 ('lot', 'log'),
 ('log', 'cog')]

然后,您可以使用此列表来找出最短的路径。每次您只需要简单地在手中搜索元组的后一个条目,就成为下一个的第一个条目。您可以在距离逻辑或最后一部分中添加对endword的检查。