[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] 。

提示:

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

解题思路

解法一:反转+排序

假设有一对单词a和b,如果a是b的后缀,比如me是time的后缀,那么就删除单词a。当遍历完所有单词后,剩下的单词就是构成索引字符串的单词。关键之处是怎么找出这些单词来,如果正向遍历单词则太过麻烦,所以本题思路就是逆向遍历单词,所以先将所有的单词进行反转,并按字典序进行排序。如果a是b的后缀,那么反转后a’就是b’的前缀,按字典序排序后,b’就紧跟在a’后面。对按字典序排序好的反转之后的单词,如果当前单词是下一个单词的前缀,则删除(跳过)它;否则计算它的长度,并加上’#'的1字符长度。

解法二:字典树

前缀树的 api 主要有以下几个:
insert(word): 插入一个单词。
search(word):查找一个单词是否存在。
startWith(word): 查找是否存在以 word 为前缀的单词。
isTail(word):查找word是否为其他单词的前缀,是则返回False,否则返回True。
这道题需要考虑特例, 比如这个列表是 [“time”, “time”, “me”, “bell”] 这种包含重复元素的情况,这里使用set集合来去重。

复杂度分析:
时间复杂度:O(N),其中N为单词长度列表中的总字符数,比如[“time”, “me”],就是 4+2=6。
空间复杂度:O(N),其中N为单词长度列表中的总字符数,比如[“time”, “me”],就是 4+2=6。

代码

解法一:反转+排序

class Solution:
    def minimumLengthEncoding(self, words: List[str]) -> int:
        N = len(words)
        # 反转之后的单词列表
        reversed_word = []
        for word in words:
            # 将单词进行反转
            reversed_word.append(word[::-1])
        # 字典序排序
        reversed_word.sort()
        res = 0
        for i in range(N):
            # 如果当前单词是下一个单词的前缀,则跳过它
            if i+1<N and reversed_word[i+1].startswith(reversed_word[i]):
                pass
            else:
                res += len(reversed_word[i]) + 1
        return res

解法二:字典树

class Trie:
    def __init__(self):
        # 初始化字典树结构
        self.Trie = {}

    def insert(self, word):
        # 向字典树中插入单词word
        curr = self.Trie
        for w in word:
            if w not in curr:
                curr[w] = {}
            curr = curr[w]
        # 标记单词结尾
        curr['#'] = 1

    def isTail(self, word):
        # 判断当前单词word是否是从根节点到叶节点组成,即是否为其他单词的前缀
        curr = self.Trie
        for w in word:
            curr = curr[w]
        return True if len(curr)==1 else False

class Solution:
    def minimumLengthEncoding(self, words: List[str]) -> int:
        trie = Trie()
        words = set(words) # 单词去重
        res = 0
        for word in words:
            trie.insert(word[::-1]) # 逆序插入
        for word in words:
            if trie.isTail(word[::-1]):
                res += len(word) + 1
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值