LeetCode 820.题目-中等

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2.解题

问题的本质是找出所有无法成为别的单词的后缀的单词。

方法一:所有单词放入集合,依次删除每个单词的后缀

相关知识:
set.discard()
思路:

  • 因为在hash set中删除操作效率高。而且放入集合可以去重。所以先讲words数组放入set中
  • 对每个单词。遍历它的所有后缀。并从set中删除
  • 注意使用set.discard()方法而不是remove()方法。后者若删除元素不存在会报错,而前者不会。
  • 复杂度分析:
    时间复杂度 O ( ∑ w i 2 ) O\left(\sum w_{i}^{2}\right) O(wi2), 其中 w i w_i wi是 words[i] 的长度。每个单词有 w i w_i wi个后缀,对于每个后缀,查询其是否在集合中时需要进行 O ( w i ) O(w_i) O(wi)的哈希值计算。
    空间复杂度 O ( ∑ w i ) O\left(\sum w_{i}\right) O(wi), 存储单词的空间开销
class Solution:
    def minimumLengthEncoding(self, words: List[str]) -> int:
        good = set(words)
        for word in words:
            for k in range(1,len(word)):
                good.discard(word[k:])
        return sum(len(word)+1 for word in good)

在这里插入图片描述

方法二:字典树

相关知识:
能自动赋初始值的字典-collections.defaultdict()方法
python中的lambda关键字
字典树Trie
python中的reduce()方法-序列迭代方法
python中的特殊方法__getitem__()方法
python中的enumerate()函数-返回枚举对象
使用__getitem__魔法函数实现多层嵌套字典:博主自己实现了多层嵌套字典的__getitem__方法,并指出collections.defaultdict类中已经实现了类似的方法(这也就是我们下面用到的)

思路:

  • 利用数组的in方法和List的index方法
  • 遍历数组的数nums[i],通过in方法**target-num[i]**判断是否在数组内,如果在,则使用index方法获得下标。(注意要判断是否是使用了重复的元素)
class Solution:
    def minimumLengthEncoding(self, words: List[str]) -> int:
        words = list(set(words)) # 去掉重复。必须要去掉重复!
        Trie = lambda: collections.defaultdict(Trie) # lambda构造函数,嵌套字典
        trie = Trie()
        # getitem方法能使对应字典出现key,但value是空的{}
        # Trie是一个嵌套字典.
        # 对任一word[i]:S来说,reduce可以看成是一个循环,嵌套过程,
        # 完成reduce()操作能得到Trie[S[0]][S[1]][S[2]]...[S[len(S)-1]]的值,记为L[i]
        # 对所有words进行这一操作, 就完成了嵌套字典的生成过程
        # 若word[i]不是别的单词的后缀, 则L[i]必是空{},即len(L[i])==0
        # 若word[i]是别的单词的后缀, 则L{i}必有值
        L = [reduce(dict.__getitem__, word[::-1], trie) for word in words]
        return sum(len(word)+1 for i, word in enumerate(words) if len(L[i]) == 0)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值