最近我被问到这个问题。
给定连续的单词流,在读取输入时删除重复项。
示例:
输入:This is next stream of question see it is a question
输出:This next stream of see it is a question
从结束开始,question
以及is
已经出现一次,所以第二次被忽略。
我的解决方案:
在此方案中为通过流的每个单词使用散列。
如果发生碰撞,则忽略该字词。
这绝对不是一个好的解决方案。我被要求优化它。
解决此问题的最佳方法是什么?
答案 0 :(得分:9)
哈希并不是一个特别糟糕的解决方案。
它提供了预期O(wordLength)
查询时间,但在最坏的情况下为O(wordLength * wordCount)
,并使用O(maxWordLength * wordCount)
空格。
备选方案:
trie是树数据结构,其中每条边对应一个字母,而根的路径定义节点的值。
这将提供O(wordLength)
查找时间并使用O(wordCount * maxWordLength)
空间,但实际空间使用率可能会更低,因为重复前缀(例如下例中的te
)仅使用空格一次。
binary search tree是树数据结构,其中以左子项为根的子树中的每个节点都小于其父节点,同样右侧的所有节点都更大。
self-balancing一个O(wordLength * log wordCount)
查询时间并使用O(wordCount * maxWordLength)
空格。
bloom filter是一个数据结构,由一些位和一些哈希函数组成,它们将一个字映射到一个位,在添加时设置每个哈希函数的输出,并检查是否在查询中没有设置任何哈希函数
这比上述解决方案占用的空间更少,但是以误报为代价 - 某些单词将被标记为不重复的单词。
具体来说,每个密钥使用1.44 log2(1/e)
位,其中e
是误报率,空间使用率O(wordCount)
,但常量因子非常低。
这将提供O(wordLength)
查询时间。
布隆过滤器的示例,表示集合
{x, y, z}
。彩色箭头显示每个集合元素映射到的位数组中的位置。元素w
不在集{x, y, z}
中,因为它散列到包含0的一个位数组位置。对于此图,m=18
和k=3
。