问题:输入是一个(不一定是排序的)序列S = k1,k2,...,n个任意数的kn。考虑形式为min {ki,kj}的n 2个数的集合C,其中1 <= i,j <= n。提供O(n)
时间和O(n)
空间算法以查找C的中位数。
到目前为止,我发现通过检查C的不同集合S,C中S中最小数字的实例数等于(2n-1),下一个最小数字:(2n-3)等等直到你只有一个最大数字的实例。
有没有办法使用这些信息来查找C的中位数?
答案 0 :(得分:19)
有很多种可能性。我喜欢的是Hoare的Select
算法。基本的想法类似于Quicksort,除了当你递归时,你只能递归到将保存你正在寻找的数字的分区。
例如,如果你想要100个数字的中位数,你可以从分区数组开始,就像在Quicksort中一样。你会得到两个分区 - 其中一个分区包含50个 th 元素。递归地在该分区中执行您的选择。继续,直到你的分区只包含一个元素,这将是中位数(并注意你可以为你选择的另一个元素做同样的事情。)
答案 1 :(得分:9)
是的,很好的谜题。我们可以在你说的那条线上找到中位数。
在C中我们有1次出现max(k),3次出现次高,5次出现次高等等
如果我们订购C的元素,则第m个最高数字左边的元素数量是m ^ 2(奇数之和)
我们感兴趣的数字(计算中位数) 一个。如果n是奇数,则(n ^ 2 + 1)/ 2 =α 湾如果n是偶数,则α1= n ^ 2/2且α2= n ^ 2/2 + 1 但alpha1 = n ^ 2/2绝不是方数=&gt;紧靠alpha1右边的数字等于alpha1(前m个奇数的和是正方形)=&gt; ALPHA1 =α-2。
因此归结为确定m使得m ^ 2(前m个奇数之和)刚好高于(n ^ 2/2)
因此,归结为确定m = ceiling(n / sqrt(2)和原始序列中的第m个最高数。(是否找到最高或最低(nm-1)是优化)。
我们可以很容易地找到第m个最高数字(只记下左边第一个最大数字)或者使用中位数算法的中位数来表示线性时间。
答案 2 :(得分:6)
维基百科有一篇关于Selection algorithms的好文章。如果您使用的是C ++,则STL包含nth_element()算法,平均线性时间。