leetcode-820.单词的压缩编码

题目描述

给定一个单词列表,我们将这个列表编码成一个索引字符串 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] 。

leetcode-820.单词的压缩编码_第1张图片

提示

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

解题思路

构造字典树,对于每个单词从后往前处理。
最后答案是每个叶子节点的层数和(编码字符串中的单词长度)+叶子节点数量(#数量)

代码实现

class Solution:
    def minimumLengthEncoding(self, words: List[str]) -> int:
        class Node:
            def __init__(self, l):
                self.l = l # 层数
                self.children = {}
        
        root = Node(0)
        def build(t, w): # 递归构造字典树
            if not w:
                return
            if w[-1] not in t.children:
                t.children[w[-1]] = Node(t.l + 1)
            build(t.children[w[-1]], w[:-1])
        for w in words:
            build(root, w)
        ans = [0] # 相当于全局变量,以便在递归中累加

        def vis(t):  # 计算答案
            if len(t.children) == 0: # 是叶子节点
                if t.l > 0:
                    ans[0] += t.l + 1 # 累加
            for c in t.children.values():
                vis(c)
        vis(root)
        return ans[0]

方法二

1、discard函数会删去set中的元素,如果不存在,不会报错
2、只要确定set中没有重复单词即可

class Solution:
    def minimumLengthEncoding(self, words: List[str]) -> int:
        word=set(words)
        sum=0
        for i in words:
            for j in range(1, len(i)):
                # discard() 方法用于移除指定的集合元素。该方法不同于 remove() 方法,因为 remove() 方              # 法在移除一个不存在的元素时会发生错误,而 discard() 方法不会。
                word.discard(i[j:])
        for k in word:
            sum+=len(k)+1
        return sum

参考资料

1.Python Set discard方法

你可能感兴趣的:(Leetcode)