答案 0 :(得分:10)
您将需要存储至少ceil(n / 2)点,因为前n / 2点中的任何一个可能是中位数。存储点并找到中位数可能是最简单的。如果保存ceil(n / 2)点是有价值的,那么在前n / 2点读入一个排序列表(二叉树可能是最好的),然后当添加新点时抛出低点或高点并保持追踪任意一端的点数。
修改强>
如果流长度未知,那么显然,正如斯蒂芬在评论中所观察到的那样,那么我们别无选择,只能记住一切。如果可能存在重复项目,我们可以使用Dolphins存储值和计数的想法来节省一些内存。
答案 1 :(得分:2)
你可以
k
不同的值意味着存储O(k)
内存)O(n)
的较小常量。答案 2 :(得分:1)
如果您有离散值和大量重复,您可以存储值和计数,这将节省一些空间。
可能在计算阶段你可以丢弃顶部的'n'和底部'n'值,只要你确定中位数不在那个顶部或底部范围内。<登记/> 例如假设您期待100,000个值。每次存储的数量达到(例如)12,000时,您可以丢弃最高1000和最低1000,将存储量减少到10,000。
如果值的分布相当一致,这将很有效。但是,如果有可能在最后接收到大量非常高或非常低的值,则可能会使计算失真。基本上,如果您丢弃小于(最终)中位数的“高”值或等于或大于(最终)中位数的“低”值,则计算结束。
<强>更新强>
一点例子
假设数据集是数字1,2,3,4,5,6,7,8,9
通过检查,中位数为5。
假设您获得的前5个数字是1,3,5,7,9
为了节省空间,我们丢弃最高和最低,留下3,5,7
现在得到两个,2,6,所以我们的存储是2,3,5,6,7
丢弃最高和最低,留下3,5,6
得到最后两个4,8,我们有3,4,5,6,8
中位数仍然是5,世界是个好地方。
但是,我们可以说前五个数字是1,2,3,4,5
丢弃顶部和底部,留下2,3,4
得到两个6,7,我们有2,3,4,6,7
丢弃顶部和底部离开3,4,6
得到最后两个8,9,我们有3,4,6,8,9
中位数为6,这是不正确的。
如果我们的数字分布均匀,我们可以继续修剪四肢。如果他们可能聚集在一大堆或许多小数字中,那么丢弃是有风险的。
答案 3 :(得分:1)
我遇到了同样的问题,但有一种方法尚未在此处发布。希望我的回答将来能对某人有所帮助。
如果您知道您的值范围,并且不太在乎中间值的精度,则可以使用常量内存逐步创建量化值的直方图。这样很容易找到量化值的中位数或任何位置。
例如,假设您的数据流是图像像素值,并且您知道这些值是都在0〜255之间的整数。要逐步创建图像直方图,只需从零开始创建256个计数器(仓),然后在扫描输入时在与像素值相对应的仓中计数1。创建直方图后,找到大于数据大小一半的第一个累积计数以获取中位数。
对于实数数据,您仍然可以计算直方图,每个bin具有量化的值(例如10、1或0.1的bin等),具体取决于期望的数据值范围和所需的精度。 / p>
如果您不知道整个数据样本的值范围,则仍可以估算中值的可能值范围,并计算该范围内的直方图。这会自然降低异常值,但正是我们在计算中位数时想要的。