【问题标题】:store top k results from count-min-sketch存储 count-min-sketch 的前 k 个结果
【发布时间】:2019-04-05 07:22:54
【问题描述】:

我需要将前 k 个最常见的元素存储在一个流中。为了估计频率,我使用 count-min-sketch 算法。我的流由键(作为字符串)组成。所以基本上每次我在我的流中遇到一个新键时,我都会通过查看 count-min-sketch 数据结构来计算当前键的频率。但是我无法存储前 k 个最常用的键。

我的第一个想法是将它们存储在一个固定大小为 k 的最小堆中。我用比较器比较频率将 [频率,键] 存储在这个最小堆中。所以每次我得到一个密钥的频率时,我都会尝试查看堆大小是否超过 k,如果是,那么我将当前密钥的频率与最小堆中的顶部(最小)频率进行比较,如果我当前的密钥是频率大于我弹出顶部,然后将我的密钥插入堆中。

但是我意识到最小堆不是一个集合,这意味着它允许重复。假设我有一个非常热的键,我一直在流中计算它,所以每次我将这个 [频率,键] 插入堆时,最终我的堆将充满相同的键,只是频率不同。

所以我想知道是否有一种好方法可以将前 k 个不同的更频繁元素存储在 count-min-sketch 中。

【问题讨论】:

    标签: java data-structures heap count-min-sketch


    【解决方案1】:

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

    如果是热项目 - 你增加计数并从 count-min 草图中获取新的频率,假设该项目已经存在于 min-heap 中,你从 hash-map 中获取项目并增加频率

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

    【讨论】:

    • 如何使用 Java 的 Priority Queue 做到这一点。没有办法共享相同的内存地址。要么你必须建立自己的 minHepa。
    【解决方案2】:

    在堆中维护 [key,<frequency,position>] 对的哈希图是有意义的。 position 指的是堆内键的索引(假设基于数组的堆)。当密钥到达时,您检查 2 个条件:
    - 密钥在哈希图中
    -它的频率发生了变化

    如果两者都是真的,你在O(1)时间找到堆中的键,因为你已经把它的位置存储在哈希图中,然后修改键的频率,根据频率是增加还是减少,你会冒泡-从该位置向下或向上冒泡 (O(logn))。更改位置后,您使用新的频率和位置值更新该键的哈希图条目。

    如果第一个是假的,你遵循一个通常的逻辑,即比较键与根,如果堆已满并且键的频率大于根的频率,那么你将根从堆中弹出并从 hashmap 中删除,同时将key插入到堆和hashmap中。

    如果 key 在 hashmap 中,但它的频率没有改变,你什么都不做。

    【讨论】:

    • 谢谢,这是个好主意。 Java 的优先队列在操作后不给出索引。所以我坚持使用priorityQueue。但你提醒我,我可以自己实现一个支持索引的二进制堆。
    猜你喜欢
    • 2020-10-28
    • 1970-01-01
    • 2023-03-28
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多