Java Program to Find Median in a Stream

2025 年 5 月 6 日 | 阅读 3 分钟

在计算和算法设计领域,数据集的中位数是人们面临的常见问题类型。中位数给出了按值升序排列的值的分布的中间点,是另一种衡量集中趋势的指标。

然而,当数据以流的形式到来并持续定期接收时,计算中位数可能非常具有挑战性。这是因为数据集不是一次性可用的,反复对大型数据集进行排序非常耗时。

理解挑战

对于静态数据集,查找中位数涉及排序并选择中间元素:如果数据集的元素数量是奇数,则中位数是数据集的中间项。当均值具有偶数大小的群组时,中位数是通过对中间群组的两个均值进行平均而生成的数字,这一点尤其正确。

然而,在流式处理环境中

这是一个数据集;组件可以一个接一个地进来。这使得每次都以 O(NlogN) 的时间复杂度对整个数据集进行排序的想法失效。这意味着必须有一种方法来有效地处理传入的元素,并仍然具备计算中位数的能力。

使用双堆方法

为了解决这个问题,我们使用了两个堆的组合

最大堆:数据集的较小一半存储在此处。该堆中的最大元素影响堆的较低一半的中值。

最小堆:回想一下,declspec 声明了一个存储在此结构中的数据集的较大一半。此堆中的最小元素定义了该堆的较高一半的中值。

通过维护这些堆

中位数可以始终以 O(1) 的常数时间找到。

添加新元素需要对数时间 O(logN)。

算法

添加新数字

  • 最大堆是完整的 二叉树,其中每个节点的值都大于其子节点的值,如果数字小于或等于最大堆的根,则将数字添加到最大堆。
  • 否则,我们需要将其插入最小堆。

平衡堆

  • 如果其中一个堆比另一个堆多一个或更多元素,则只需将一个元素从该堆传输到另一个堆。这有助于将两者的大小差异保持在最多 1。

查找中位数

  • 如果两个堆的大小相等,则中位数等于堆根的平均值。
  • 在这种情况下,如果堆的大小不相等,则分布的中位数是第二个堆的平方根。

文件名:MedianFinder.java

输出

 
Stream: 
12  -> Median: 12.0
4  -> Median: 8.0
5  -> Median: 5.0
3  -> Median: 4.5
8  -> Median: 5.0
7  -> Median: 6.0   

优点

效率:这种方法非常适合实时系统。

可扩展性:更新也具有对数时间复杂度,这使得这种类型的树可以随着数据集进行扩展。

结论

通过理想的双堆结构,可以几乎实时地确定流序列的中位数。这种方法具有简单性和高效性的优点,使其适用于许多情况。从简单地制作小数据集的数组到处理高速数字计算系统中的海量流数据,这种 Java 实现高效且可靠。