是否存在根据动态确定的中值将一组随机数分成两组的算法(不对它们进行排序)?
实施例。如果我有序列2-3-6-7-1-4-5,结果将是两个分开的组:
A)1 2 3
B)5 6 7
中位数价值:4
答案 0 :(得分:3)
您可以在linear time中找到数组(和拆分)的中位数。
答案 1 :(得分:0)
是的,这可以在 O(n)。
中完成首先,如果我们已经知道中位数,我们可以通过迭代序列并将每个值与中位数进行比较,轻松地将序列分成两个 O(n)。那么我们如何在 O(n)?
中找到中位数基本思想是使用quicksort,但不是递归排序数据透视的两边,只对包含中位数的一半进行排序(即包含指数的一半) ⌈n/2⌉
)。如果我们选择一个枢轴保证快速排序的几何收敛(如median-of-medians那样),那么我们的整体算法将是O(n)。
让我们调用数组的当前大小 k ,并且由于中位数中位数 c 而减少 - 即。我们的支点保证阵列每步缩小至少 c
⌈n/2⌉
)的数组的一半。这个新的子数组的大小不会超过k/c
。重复步骤1& 2递归,直到我们确定了原始数组中的位置为⌈n/2⌉
的元素。该算法的渐近运行时间为
2 O(n)+ 2 O(n / c)+ 2 O(n / c 2 )+ 2 O(n / c 3 )+ ...
= O(n)
答案 2 :(得分:0)
BFPRT(Blum-Floyd-Pratt-Rivest-Tarjan)算法(查看wiki)可以找到线性时间的中位数,即O(n)
。
然而,O
- 符号中的常量“隐藏”是如此之大,以至于对于实践而言,在O(n log n)
中对数组进行排序以获得合理的数组大小会更快。
答案 3 :(得分:-1)
您可以通过查找最低楼层(n / 2)与最低楼层(n / 2)之间的平均值来找到中位数。这可以在previous SO question的帮助下完成。
之后,只需遍历您的数组,将大于中位数的元素放入一个中,然后将中位数放入另一个中。
或者,如果您知道序列的大小,则可以创建两个大小为(n / 2)的集合:一个“最小的一半”( S )和一个“最大的一半”( L ),然后逐个:
我相信这是O(n)时间;如果我错了,有人会纠正我。我能想象的最糟糕的情况是原始序列按降序排序。
ruby实现(具有很多非性能快捷方式):
def split_into_halves to_split
s = []
l = []
medianlimit = to_split.size/2
for e in to_split
if s.size < medianlimit
s.push(e)
else
if s.max >= n
max = s.max
s.delete max
s.push(e)
else
max = e
end
if l.size < medianlimit
l.push(max)
elsif l.max >= max
l.delete l.max
l.push(max)
end
end
end
return [s,l]
end
k = [2,3,6,7,1,4,5]
split_into_halves(k) #=> [[2,3,1],[6,4,5]]