python编码解码单词_LeetCode刷题--单词的压缩编码(Python)

题目信息:820单词的压缩编码单词的压缩编码

难度: 中等

分析和最初的答案

检查一个单词是不是另一个单词的后缀, 如果是, 这个单词不编码.

那我最先想到的就是遍历单词表, 删除这个单词的每个后缀, 最终保留所有不是其他单词后缀的单词

def foo(words):

words_ = set(words)

for w in words:

for i in range(1, len(w)):

words_.discard(w[i:])

return sum(len(w)+1 for w in words_)

上面是看了官方题解后修改的, 原先不熟悉集合的用法:

def foo(words):

words = list(set(words))

for w in words.copy():

for i in range(1, len(w)):

words = [j for j in words if j != w[i:]] # 这里如果用生成器会有问题, i和w的引用会改变

return sum(len(w)+1 for w in words)

复杂度分析:时间复杂度, 对每个单词所有后缀要进行检查

(没有开启对数学公式的支持, 先语言描述吧)空间复杂度: 所有单词的长度(x2)

字典树

基本性质:根节点不包含字符,除根节点外每一个节点都只包含一个字符

从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串

这是维护字符串的前缀的特点每个节点的所有子节点包含的字符都不相同。

分析与官方答案

这里只需倒着构建字典树,最终每一条路径(从二级节点到叶节点)就是不是其他单词后缀的单词,但是统计所有完整路径的效率并不高(字典树擅长的是检查,从一端开始检查而不必遍历所有单词,适合找出一条路径),可以检查每一个单词。LeetCode官方的字典树解法保存了每个单词第一个字母所在的节点,用以判断这个这个单词是否能占有一条完整的路径,即判断是否是不是其他单词后缀的单词,同时遍历单词表和节点表,用单词表里的单词来统计字符串长度。

from collections import defaultdict

from functools import reduce

def foo(words):

words = list(set(words))

# Tire是一个返回defaultdict的函数,defaultdict的默认值又是Tire

Trie = lambda: defaultdict(Trie)

trie = Trie()

# 所有单词对应的第一个字母所在的节点

nodes = [reduce(dict.__getitem__, word[::-1], trie)

for word in words]

# 同时遍历单词表和节点表

return sum(len(word) + 1

for word, node in zip(words, nodes)

if len(node) == 0)

实现一个字典树

class Trie:

def __init__(self):

self._trie = {}

def insert(self, word):

node = self._trie

for c in word:

if c not in node:

node[c]={}

node = node[c]

node['#'] = True

def delete(self, word):

node = self._trie

for c in word:

if c in node:

node = node[c]

else:

return

node.pop('#', None)

def __contains__(self, word):

node = self._trie

for c in word:

if c in node:

node = node[c]

else:

return False

if '#' in node:

return True

else:

return False

排序后检查

单词按照字母顺序排序后,前缀相同的单词相邻

因而可以反转后排序,再遍历,检查一个单词和它下一个单词(如果是默认的排序)

def foo3(words):

words = sorted(set(words), key=lambda w:w[::-1])

N = len(words)

words = [w for i,w in enumerate(words) if not (i+1

return sum(len(w)+1 for w in words)

字典树是真的没有学过,但是这个方法也没有想到,就想着暴力遍历了。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值