【发布时间】:2015-05-26 15:03:45
【问题描述】:
给定一个数据序列(它可能有重复),一个固定大小的移动窗口,在每次迭代时从数据序列的开始移动窗口,使得 (1) 从窗口中删除最旧的数据元素,并将新的数据元素推入窗口 (2) 求每次移动时窗口内数据的中位数。
这里的窗口大小是 7,我们称之为 m。 m = 窗口大小 n = 序列中的元素个数,可以是 1000 或 10000
Median for 4, 6, 99, 10, 90, 12, 17,1,21,32 : 12
Median for 6, 99, 10, 90, 12, 17, 1,21,32 : 12
Median for 99, 10, 90, 12, 17, 1, 21,32 : 17
Median for 10, 90, 12, 17, 1, 21, 32 : 17
我每次都在快速排序 m 个元素的帮助下实现了这个东西,(三个的中位数作为枢轴)。但这需要很多时间。每次排序都是必需的。我应该实现here 提到的最小和最大堆解决方案@
最小-最大堆解决方案中的问题:
当一个新数据被推入窗口时,从其中一个堆中删除最旧的数据,并将新数据与最大和最小堆的顶部进行比较,以确定哪个堆要放置的数据。然后,就像在第一次迭代中一样找到中位数。
如何找到从堆中删除最旧的数据,我们如何维护它。根据给定的示例,第二次 4 是最旧的元素,第三次 6 是最旧的元素。我们如何从堆中删除它。
上述问题的后续问题,如何在堆中查找数据元素是一个问题。堆是二叉树而不是二叉搜索树。
任何帮助将不胜感激。
编辑:我已经有输入数据,所以没有插入发生。只发生在固定大小的队列或窗口上,而不是实际的输入序列。
谢谢
【问题讨论】:
-
正常的方法是保持反向指针将堆索引映射到数组位置,数组位置映射到堆索引,然后堆交换和其他操作有足够的信息来维护。
-
@doynax 你能解释一下吗?没看懂你说的什么
-
@sam_k 关于您的编辑,每次窗口移动时都会发生插入和删除。
-
@sam_k:我建议您在两个方向上交叉引用数据结构,以便您的操作可以有效地实现双向。对于当前窗口中的每个元素,您都在存储它的堆中维护一个索引,相反,对于每个堆条目,您都为要找到数据的窗口保留一个索引。每当一个项目在堆上移动时,您都会查看堆到窗口索引并使用它来更新反向的窗口到堆索引,使其返回到新的堆位置。
-
感谢@doynax 的评论。我会尽力理解你所说的。我是数据结构的新手,会尝试理解这一点。如果可能的话,用示例来解释你的答案作为这篇文章的答案。
标签: c++ algorithm data-structures heap