存储来自最小计数的前k个结果

时间:2018-11-01 03:55:21

标签: java data-structures heap

我需要在流中存储前k个最频繁的元素。为了估计频率,我使用了最小计数素描算法。我的流包含键(作为字符串)。因此,基本上,每次我在流中遇到新密钥时,我都会通过查看最小计数素描数据结构来计算当前密钥的频率。但是我无法存储前k个最频繁的键。

我的第一个想法是将它们存储在固定大小为k的最小堆中。我将[频率,密钥]与比较器比较频率一起存储在此最小堆中。因此,每当我获得密钥的频率时,我都会尝试查看堆大小是否超过k(如果大于),然后将当前密钥的频率与min-heap中的最高(最小)频率进行比较(如果当前密钥为频率更大,然后我弹出顶部,然后将密钥插入堆中。

但是我意识到最小堆不是一个集合,这意味着它允许重复。假设我有一个非常热的密钥,并且我一直在流中对其进行计数,因此,每当我将此[频率,密钥]插入堆中时,最终我的堆将充满相同的密钥,只是频率不同。

所以我想知道是否有一种好方法可以将前k个最常见的元素存储在count-min-sketch中。

2 个答案:

答案 0 :(得分:0)

有意义地维护堆中已经存在的[key,<frequency,position>]对哈希表。 position引用堆内键的索引(假设基于数组的堆)。钥匙到达时,您检查2个条件:
-密钥在哈希图中
-它的频率已更改

如果两个都成立,则您在O(1)时间内在堆中找到了密钥,因为它的位置已经存储在哈希图中,然后修改密钥的频率,并根据频率是增加还是减少来执行从该位置(O(logn)开始冒泡或冒泡。更改位置后,可以使用新的频率和位置值更新该键的哈希表条目。

如果第一个错误,则遵循通常的逻辑,即将密钥与根进行比较,如果堆已满且密钥的频率大于根的频率,则将根从堆中弹出并将其从哈希图中删除,并将密钥插入到堆和哈希图中。

如果键在哈希图中,但其频率未更改,则您什么也不做。

答案 1 :(得分:0)

您还可以维护所有三个数据结构1.最小计数草图以存储您在流中遇到的所有内容2.最小大小为k的堆3.大小为k的哈希图

如果是热门商品-您可以增加数量并从count-min草图中获取新的频率,假设该商品已存在于min-heap中,则可以从哈希图中获取该商品并提高频率

当您遇到另一个频率刚刚增加并进入著名的min-heap的项目时,您可以同时从min-heap和hash-map中逐出根,因此从根本上说min-heap可帮助您保持前k个频率项和哈希图以随机访问那些频繁项。请注意,min-heap和hash-map都可以映射到相同的内存地址,因此只能对hash-map中存储的项目进行更新频率