每日一题,每日一练.13单词的压缩编码(字典树是什么?有用的知识增加了!)

  1. 单词的压缩编码 给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A。

例如,如果这个列表是 [“time”, “me”, “bell”],我们就可以将其
表示为 S = “time#bell#” 和 indexes = [0, 2, 5]。

对于每一个索引,我们可以通过从字符串 S 中索引的位置开始读取字符串,直到 “#” 结束,来恢复我们之前的单词列表。
那么成功对给定单词列表进行编码的最小字符串长度是多少呢?

示例:

输入: words = [“time”, “me”, “bell”] 输出: 10 说明: S =“time#bell#” , indexes = [0, 2, 5] 。

提示:

1 <= words.length <= 2000 1 <= words[i].length <= 7 每个单词都是小写字母 。

这道题的基本思路是,如果有一个单词是另一个单词的后缀,那么我们这两个词共用一个“#”终止符,只不过起始的索引位置不一,所以我们创造一个word的集合,对集合里的每个词,我们在集合中删去他们的所有后缀(因为这个后缀不需要#做额外编码),然后集合保留下来的词就是我们需要用“#”额外编码,返回他们的总长度和他们的数量(每个词都需要一个“#“)

代码如下

class Solution:
    def minimumLengthEncoding(self, words: List[str]) -> int:
        a=set(words)
        co=0
        for i in words:
            for c in range(1,len(i)):
                a.discard(i[c:])
        co=len(a)
        for d in a:
            co=co+len(d)
        return co

进入正篇,字典树

字典树的架构和树的架构是这样对应的

节点:路径上的字母组成的单词
路径:字母

根节点是空的,是的因为根节点没有任何路径来组成单词,然后第一个字母不同,第一个路径也不同,沿着路径下去,收集路径字母,我们会在每个叶子节点拼成最终想要的单词,并且在这条路径产生分叉时,记录之前相同的节点。在单词上反映的就是公共前缀,但是我们这一题需要公共后缀,所以我们反向来记录单词,由后往前,如果我们有一条路径没出现新的叶子(沿着之前的路径可以收集出这个单词),那么就被认为有公共后缀,也就是说,当所有单词入树后,所有叶子结点上的单词就包含了我们需要的长度,其余的单词在未至叶子结点时已经存在树的某个节点中(即公共后缀的情况)
实在没空搭一个了,所以这种方法把官方题解拿过来了

class Solution:
    def minimumLengthEncoding(self, words: List[str]) -> int:
        words = list(set(words)) #remove duplicates
        #Trie is a nested dictionary with nodes created
        # when fetched entries are missing
        Trie = lambda: collections.defaultdict(Trie)
        trie = Trie()#建一个树

        #reduce(..., S, trie) is trie[S[0]][S[1]][S[2]][...][S[S.length - 1]]
        nodes = [reduce(dict.__getitem__, word[::-1], trie)
                 for word in words]#录入

        #Add word to the answer if it's node has no neighbors
        return sum(len(word) + 1
                   for i, word in enumerate(words)
                   if len(nodes[i]) == 0)#返回叶子节点总长+“#”
              

有用的知识增加了!!

你可能感兴趣的:(每日一题,每日一练.13单词的压缩编码(字典树是什么?有用的知识增加了!))