Jiang's blog

每日一道算法之--单词的压缩编码

Word count: 595Reading time: 2 min
2020/03/28 Share

单词的压缩编码

力扣第820题:https://leetcode-cn.com/problems/short-encoding-of-words/

给定一个单词列表,我们将这个列表编码成一个索引字符串 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution:
def minimumLengthEncoding(self, words: List[str]) -> int:
if not words:
return 0
# 将字符串安安后缀排序
words.sort(key = lambda x: x[::-1],reverse=True)
# 记录新字符串的长度
lenght = 0
# 这个变量是更新比较的字符串
word_compare = ''
for i in range(len(words)):
# 如果该单词是比较字符串的后缀,直接忽略
if word_compare.endswith(words[i]):
continue
# 更新新字符串长度,包括一个‘#’
lenght += len(words[i]) + 1
# 更新比较的字符串
word_compare = words[i]
return lenght

复杂度分析

时间复杂度: 将字符串排序的时间复杂度为 O(nlogn), 然后只需遍历一次列表就能完成压缩,时间复杂度为 O(n),所以总的时间复杂度为 O(nlogn)。

空间复杂度: 用了两个变量,所以空间复杂度为O(1)。


2. 字典树/Trie树

去找到是否不同的单词具有相同的后缀,我们可以将其反序之后插入字典树中。例如,我们有 “time” 和 “me”,可以将 “emit” 和 “em” 插入字典树中。

GAeUYj.png

1
2
3
4
5
6
7
8
9
10
11
12
class Solution:
def minimumLengthEncoding(self, words: List[str]) -> int:
words = list(set(words))
Trie = lambda: collections.defaultdict(Trie)
trie = Trie()

nodes = [reduce(dict.__getitem__, word[::-1], trie)
for word in words]
print(words)s
return sum(len(word) + 1
for i, word in enumerate(words)
if len(nodes[i]) == 0)

GAml4J.png

参考至力扣题解:https://leetcode-cn.com/problems/short-encoding-of-words/solution/dan-ci-de-ya-suo-bian-ma-by-leetcode-solution/

CATALOG
  1. 1. 单词的压缩编码
    1. 1.0.1. 1. 字符串翻转 + 排序
    2. 1.0.2. 复杂度分析
  2. 1.1. 2. 字典树/Trie树