计算运行中位数的算法?


18

在较小的窗口上,n log n排序可能会起作用。有没有更好的算法可以做到这一点?


1
我认为这是第一个移至Stack Overflow的候选人。

可能,但是在SO方面需要更多解释。
walkytalky

2
大多数程序员都知道“中位数”。(sort(array))[length / 2]对于那些忘记的人来说是一个足够大的暗示。同样,对于每个新点,在最基本的情况下,您只需要对阵列的一半进行二等分/插入...
Paul 2010年


2
太琐碎,不仅仅只是注释,而中位数3s的代码只是a + b + c-max(a,b,c)-min(a,b。c)。即使存在联系,也可以正常工作。只有在我从其他人的代码中想到了这一点后,这对我来说才是显而易见的(为什么他(在这种情况下)为什么要进行加法和减法以获得中位数??),而其他几个人可能会有相同的反应。max()和min()通常实现为超快速函数。可悲的是,总体上没有这样的把戏。
尼克·考克斯

Answers:


11

对数组进行排序以计算中位数是不好的形式。中位数(和其他分位数)通常使用快速选择算法计算,复杂度为O(n)

您可能还希望我的回答一下最近相关的问题在这里



6

如果您愿意接受近似值,则可以使用其他方法。例如,一个近似值是其秩在距真实中位数一定(用户指定)距离之内的值。例如,中位数(归一化)排名为0.5,如果您指定10%的误差项,则您希望答案的排名介于0.45和0.55之间。

如果这样的答案是适当的,那么有许多解决方案可以在滑动数据窗口上工作。基本思想是维护一定大小(大约1个/误差项)的数据样本,并计算该样本的中位数。可以证明,无论输入的性质如何,所得的中位数都满足我上面提到的属性。

因此,主要问题是如何维护一定大小的数据的运行样本,对此有很多方法,包括称为储层采样的技术。例如,本文:http : //citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.7136


4

如果您将长度为k的数据窗口维护为排序的双链表,则可以通过二进制搜索(在每个新元素移入窗口时插入每个新元素)和圆形指针数组(以立即定位那些需要删除),则窗口的每次移位都需要O(log(k))努力才能插入一个元素,只有O(1)努力才能删除移出窗口的元素,并且只有O(1)努力才能找到中位数(因为每次将一个元素插入或删除到列表中,您都可以在O(1)时间中更新指向中位数的指针)。因此,用于处理长度为N的数组的总工作量为O((nk)log(k))<= O(n log(k))。这比到目前为止提出的任何其他方法都要好,这不是一个近似值,这是准确的。


1
您能否详细说明如何建议在已排序的双向链接列表中进行二进制搜索?
NPE

一个“链接”可让您按排序顺序遍历列表;另一个允许您按元素出现的顺序遍历。不过,还不清楚如何使用指针来完成此操作,就像@aix问题一样。
shabbychef

2
@aix我认为您的暗示是正确的;我需要一个可索引的跳过列表,而不仅仅是排序的双向链接列表。想法是要有一个数据结构,该数据结构允许插入一个元素,删除一个元素,并找到期望的O(log(n))时间(或更好)的中值。
ub

3

正如您提到的,排序将O(n·log n)针对一个长度的窗口n。这样做会增加l=vectorlength总成本O(l·n·log n)

最简单的方法是在从一个窗口移到下一个窗口时,在内存中保留最后n个元素的有序列表。由于将一个元素从/从有序列表中删除/插入都O(n)将导致成本为O(l·n)

伪代码:

l = length(input)
aidvector = sort(input(1:n))
output(i) = aid(n/2)
for i = n+1:l
    remove input(i-n) from aidvector
    sort aid(n) into aidvector
    output(i) = aid(n/2)


2

如果您可以接受估计值而不是真实的中位数,则补救算法(PDF)是一次通过,具有较低的存储要求和明确定义的准确性。

以b为基础的救济者通过计算b个观察值组的中位数,然后计算这些中位数的中位数,直到仅剩下一个估计值来进行处理。该方法只需要k个大小为b的数组(其中n = b ^ k)...


0

我在嵌入式应用程序中使用了RunningStats C ++库。这是我发现的最简单的运行统计数据库。

从链接:

该代码是Knuth和Welford方法的扩展,用于通过一次数据计算标准偏差。它也可以通过类似的界面计算偏度和峰度。除了只需要遍历数据之外,该算法在数值上稳定且准确。


该网页上有没有提及中位数?
musiphil
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.