在具有重复项的长数据序列的滚动窗口中查找模式
find mode in a rolling window of a long sequence of data with duplicates
给出一个数据序列(带有重复数据),沿着数据序列移动一个固定大小的窗口,并在每次迭代时在窗口中查找模式,其中删除最旧的数据,并将新数据插入到窗口中。
我在这里找不到更好的解决方案。
我的想法:使用哈希表,键是数据,键的数据是数据在窗口中出现的频率。
在第一次迭代时,迭代窗口中的每个数据并将其放入哈希表,同时计算每个数据的频率。之后,遍历哈希表并返回频率最高的数据。对于接下来的每次迭代,搜索哈希表中最旧的数据,如果它在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中检索具有被删除值的频率的所有条目,并找到具有正确值的条目。在映射和多映射中删除、更改和重新插入节点,以处理删除的数据;使用类似的过程来处理添加的数据。根据您期望的数据,可能值得首先检查要插入的值是否与要删除的值匹配。
- 如何在Qt窗口小部件中使用QStringView(或QStringRef)
- 使用一个考虑到std::map中键值的滚动或换行的键
- 问:如何使用C++中的按钮从窗口打开窗口
- SDL 窗口不会弹出
- 在createdialog创建的窗口中捕获用于编辑控件的OnMouseMove消息
- 如何在cpp文件之间切换窗口?在Qt中
- QuadTree只在窗口的右上角绘制
- VS Code "command":"make"与终端窗口中的命令行"make"不同
- 如何初始化升压滚动窗口累加器?
- 有没有办法有条件地检查窗口是否正在使用滚动条
- 如何隐藏显示HTML5标记的Web浏览器控件(IE)的滚动条和窗口边框
- 滚动条缩略图跟踪长度 基于图像的水平适合调整窗口大小时出现问题
- 如何模拟当前打开窗口的鼠标滚动
- 通过手指触摸在窗口之间水平(向后/向前)滚动
- 在具有重复项的长数据序列的滚动窗口中查找模式
- 如何使用他的HWND检查窗口是否有可见的滚动条
- Visual Studio汇编程序窗口将永远滚动
- 在滚动窗口上应用矩阵乘法的最聪明的方法
- 添加水平滚动条来调整窗口对话框的大小
- Qt调整窗口大小以适应滚动区域问题中的纵横比