有没有办法找到未排序数组的中位数: 1-没有排序。 2-不使用选择算法,也不使用中位数的中位数
我发现了许多类似于我的其他问题。但解决方案,其中大部分,如果不是全部,讨论了SelectProblem和MedianOfMedians
答案 0 :(得分:13)
你可以在没有排序的情况下找到数组的中位数。有效的做法并不容易。
例如,您可以迭代数组的元素;对于每个元素,计算小于等于它的元素数,直到找到具有正确计数的值。这将是O(n 2 )时间,但只有O(1)空间。
或者你可以使用一个最小堆,其大小只是数组大小的一半。 (也就是说,如果数组具有std
或2k
元素,则堆应该具有2k+1
个元素。)使用标准堆构建算法使用第一个数组元素构建堆(这是O(N))。然后,对于每个剩余的元素k+1
,如果x
大于堆的最小值,则将min元素替换为x
并执行SiftUp操作(即O(log) N))。最后,中值是堆的最小元素(如果原始数组的大小是奇数)或者是堆中两个最小元素的平均值。因此,如果不能重新排列数组元素,那么总共有O(n log n)时间和O(n)空间。 (如果您可以重新排列数组元素,则可以就地执行此操作。)
答案 1 :(得分:4)
有一种随机算法能够在O(n)
步骤(平均情况场景)中完成此任务,但它确实涉及对数组的某些子集进行排序。并且,由于其随机性,不能保证它实际上会完成(尽管这种不幸的事件应该以消失的概率发生)。
我将在这里留下主要想法。有关此算法工作原理的更详细说明和证据,请查看here。
让A
成为您的数组并让n=|A|
。让我们假设A
的所有元素都是不同的。算法如下:
t = n^(3/4)
随机选择A
个元素。 T
成为所选元素的“集合”。排序T
。pl = T[t/2-sqrt(n)]
和pr = T[t/2+sqrt(n)]
。A
的元素并确定有多少元素小于pl
(由l
表示)以及多少元素大于pr
(由{表示} {1}})。如果是r
或l > n/2
,请返回第1步。r > n/2
成为M
和A
之间pl
中的元素集。 pr
可以在步骤4中确定,以防万一我们到达第5步。如果M
的大小不超过M
,请排序4t
。否则,请返回步骤1. M
作为中位元素。算法背后的主要思想是获得包含中间元素的两个元素(m = M[n/2-l]
和pl
)(即pr
< pl
< {{ 1}})这两个在数组的有序版本中彼此非常接近(并且在没有实际排序数组的情况下这样做)。很有可能,所有六个步骤只需要执行一次(即,您将获得m
和pr
来自第一个并且仅通过步骤1-5的这些“好”属性,所以不要去回到步骤1)。一旦找到两个这样的元素,您可以简单地对它们之间的元素进行排序,并找到pl
的中间元素。
第2步和第5步确实涉及一些排序(这可能违背了你神秘建立的“规则”:p)。如果在表上对子数组进行排序,则应使用一些排序方法在pr
步骤中执行此操作,其中A
是要排序的数组的大小。由于O(slogs)
和s
明显小于T
,因此排序步骤采用“少于”M
步骤。如果它也违反了对子数组进行排序的规则,那么考虑到在这两种情况下都不需要排序。您只需要找到一种方法来确定A
,O(n)
和pl
,这只是另一个选择问题(具有相应的索引)。排序pr
和m
确实可以实现此目的,您可以使用任何其他选择方法(可能是之前建议的rici)。
答案 2 :(得分:0)
http://www.aip.de/groups/soe/local/numres/bookfpdf/f8-5.pdf描述了非破坏性的常规selip()。它通过数据进行多次传递,在每个阶段随机选择当前值范围内的项目,然后计算项目数量以建立随机选择的等级。