🥈Medium
给定一个单词列表,我们将这个列表编码成一个索引字符串 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
- 每个单词都是小写字母
题解
十个月前做过的题目,今天再拿起来又不会了。这种接连失败的状态什么时候可以到头。真的好想努力之后能看到好的结果🙏🙏🙏。
方法一:存储后缀
如果单词X是Y的后缀,那编码Y的时候就同时将X编码了。如果单词X不在任何单词Y的后缀中出现,那X一定是编码字符串的一部分。
因此,目标就是保留所有不是其他单词后缀的单词,最后的结果就是这些单词长度加一的总和(每个单词后需加#)
Python
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)
JavaScript
/*** @param {string[]} words* @return {number}*/var minimumLengthEncoding = function(words) {const wordSet = new Set(words)for (let i in words){for(let j = 1;j<words[i].length;j++){wordSet.delete(words[i].slice(j))}}let sum=0wordSet.forEach(item => sum+=item.length+1)return sum};
复杂度分析
- 时间复杂度:
,其中是
word[i]的长度。每一个单词有个后缀,对于每个后缀,查询其是否在集合中需要
的哈希值计算
- 空间复杂度:
,存储单词的空间开销
方法二:字典树
目的就是保留所有不是其他单词后缀的单词。可以去找到是否不同的单词具有相同的后缀,我们可以将其反序之后插入字典树中。这样emit和em才有前缀关系,直接用time和me是没有前缀关系的。例如,我们有 “time” 和 “me”,可以将 “emit” 和 “em” 插入字典树中。
