有没有一种方法可以找到未排序数组的中位数: 1- 不用排序。 2- 不使用选择算法或中位数算法。
我发现很多类似于我的问题。但是其中大部分解决方案都讨论了SelectProblem和MedianOfMedians算法。
有没有一种方法可以找到未排序数组的中位数: 1- 不用排序。 2- 不使用选择算法或中位数算法。
我发现很多类似于我的问题。但是其中大部分解决方案都讨论了SelectProblem和MedianOfMedians算法。
2k
或2k+1
个元素,则堆应该有k+1
个元素)。使用第一个数组元素构建堆,使用标准堆构建算法(O(N))构建堆。然后,对于每个剩余的元素x
,如果x
大于堆的最小值,则用x
替换最小元素并执行SiftUp操作(O(log N))。最后,中位数要么是堆的最小元素(如果原始数组大小为奇数),要么是堆中两个最小元素的平均值。所以总时间复杂度为O(n log n),如果你不能重新排列数组元素,则空间复杂度为O(n)。(如果你可以重排数组元素,则可以原地执行此操作。)有一种随机算法可以在 O(n)
步骤内完成此任务(平均情况),但它确实涉及对数组的某些子集进行排序。并且,由于其随机性质,无法保证它会真正完成(尽管这种不幸的事件应该以消失的概率发生)。
我将在此留下主要思想。有关更详细的说明以及为什么此算法有效的证明,请查看此处。
设A
为您的数组,令n=|A|
。假设所有A
的元素都是不同的。算法步骤如下:
A
中随机选择 t = n^(3/4)
个元素。T
为所选元素的“集合”。对 T
进行排序。pl = T[t/2-sqrt(n)]
和 pr = T[t/2+sqrt(n)]
。A
的元素,并确定有多少个元素小于 pl
(用 l
表示),有多少个元素大于 pr
(用 r
表示)。如果 l > n/2
或者 r > n/2
,返回到步骤 1。M
成为在 pl
和 pr
之间的 A
的元素集合。如果我们到达步骤 5,则可以在步骤 4 中确定 M
的大小是否不超过 4t
,并对其进行排序。否则,返回到步骤 1。m = M[n/2-l]
作为中位数元素返回。pl
和 pr
),这两个元素包含中位数元素(即 pl
< m
< pr
),并且在数组的有序版本中这两个元素非常接近(而不需要实际对数组进行排序)。高概率情况下,所有六个步骤只需要执行一次(也就是说,你将从第一次通过步骤1-5获得具有这些“好”属性的pl
和pr
,因此不需要返回到步骤1)。一旦找到这样的两个元素,您可以简单地对它们之间的元素进行排序,并找到A
的中位数元素。
第二步和第五步确实涉及一些排序(这可能违反了您神秘地建立的“规则” :p)。如果对子数组进行排序是可行的,您应该使用某种在O(slogs)
步骤中完成此操作的排序方法,其中s
是要排序的数组的大小。由于T
和M
显着小于A
,因此排序步骤需要“少于”O(n)
步骤。如果对于排序子数组也违反规则,则应考虑到在两种情况下都不真正需要排序。您只需要找到一种确定pl
、pr
和m
的方法,这只是另一个选择问题(具有相应的索引)。虽然对T
和M
进行排序可以实现这一点,但您可以使用任何其他选择方法(也许是rici之前建议的方法)。