在具有重复项的长数据序列的滚动窗口中查找模式

find mode in a rolling window of a long sequence of data with duplicates

本文关键字:滚动 窗口 模式 查找 数据      更新时间:2023-10-16

给出一个数据序列(带有重复数据),沿着数据序列移动一个固定大小的窗口,并在每次迭代时在窗口中查找模式,其中删除最旧的数据,并将新数据插入到窗口中。

我在这里找不到更好的解决方案。

我的想法:使用哈希表,键是数据,键的数据是数据在窗口中出现的频率。

在第一次迭代时,迭代窗口中的每个数据并将其放入哈希表,同时计算每个数据的频率。之后,遍历哈希表并返回频率最高的数据。对于接下来的每次迭代,搜索哈希表中最旧的数据,如果它在hahstable中,则将其频率降低1。如果它变为0,则使用新数据替换旧数据。否则,只需将新数据插入hahstable即可。遍历表格并返回模式。

它是O(n*m),其中n是数据序列大小,m是窗口大小。缺点是:哈希表的大小不是固定的,它可能会有调整大小的开销。每次迭代,都必须遍历表,这是不有效的。

用O(n lg m)或O(n)做这件事可能吗?

感谢您的帮助。

感谢

另一种解决方案:在第一次迭代中,构建一个哈希表,将数据作为关键字,将其频率作为与关键字关联的值。在哈希表的基础上,构建一个以频率为键、以关联数据为值的多映射。

之后,在每次迭代时,在窗口中,删除最旧的数据并更新哈希表,然后用哈希表中最新更新的数据更新多映射。如果映射键有多个数据,请仅用频率未更改的数据替换新的数据。但是,添加一对新的频率和数据。

在窗口中,获取新数据并更新哈希表,使用哈希表中最新更新的数据更新多映射。

位于多映射(二进制搜索树)最右侧的条目是模式,因为它的值是当前窗口中的最高频率。

时间O(m+m*lg m+n*lg m)如果n>>m。空间:O(m)

有更好的主意吗?

空间O(M):

  • 一个环形缓冲区,用于保存M个值
  • 一个BST持有M个{值,PQ指针}对
  • 一个优先级队列,包含M个计数

及时更新O(lg M):

  • 在环形缓冲器CCD_ 1中找到偏离值
  • 在BST O(lg M)中找到相同的值
  • 调整链接的PQ节点中的计数。
    • 对该节点O(lg M)执行优先级调整
  • 用新的O(1)替换旧的环形缓冲区条目
  • 在BST O(lg M)中查找新值
  • 调整链接的PQ节点中的计数。
    • 对该节点O(lg M)执行优先级调整
  • 在PQ上GetFirst查找模式O(1)

您可以通过向BST结构添加一个nextItem指针,并保留一个指向最旧项的外部指针来消除环形缓冲区。这样可以通过一次BST查找来加快速度,如果值大小大于指针大小,则可能会赢得空间。但该算法的编码变得更加复杂。

回顾上一个问题的解决方案。。。

维护数据值的环形缓冲区。制作一个作为频率/数据值对的类型。

维护一张以数据为基础的地图;制作一个基于频率的多映射,也包含这样的对。

在数据前进的每一步中,模式是映射中键控频率的最后一个条目。可能会有平局——如何处理这是读者的一个练习。报告模式后,您需要使用映射来查找属于要删除的值的对;然后从multimap中检索具有被删除值的频率的所有条目,并找到具有正确值的条目。在映射和多映射中删除、更改和重新插入节点,以处理删除的数据;使用类似的过程来处理添加的数据。根据您期望的数据,可能值得首先检查要插入的值是否与要删除的值匹配。