按顺序查找数组中最大的10%数字

时间:2010-02-28 16:33:17

标签: algorithm sorting

给定具有'N'个数字的数组(N> 100)。我们怎样才能找到最大的10%? (如果n / 10不是整数,我们可以将它舍入)

我提出了3种算法来尝试上述问题,但我不确定哪种算法在渐近运行时最好。我是否可以进行任何修改以减少渐近时间?另外,如果N变得非常大,哪种算法可能仍然有效?

我列出了我对下面算法的想法,并且可以真正使用一些帮助来找出最有效的算法。

ALGO-1

我使用了选择排序,并在10%的数字排序后停止了它。

ALGO-2

我构建了一个最大堆并且不断删除最大的10%的数字

ALGO-3

没有实现这个,但我的想法是使用任何order-statistic算法来查找包含前10%数字的分区,然后使用合并排序对它们进行排序。

8 个答案:

答案 0 :(得分:7)

最快的解决方案是使用在O(n)中运行的partition-based selection algorithm。它基于quicksort的想法,除了不是递归地对两个分区进行排序,你只需要去其中一个分区来找到k-th最小的元素。

通过搜索k=(90%*N)-th最小数字来找到最大的10%。

如果您还记得quicksort中的分区是如何工作的,那么小于枢轴的元素会向左移动,其余元素会向右移动。假设您要选择k-th最小元素。然后,您会看到枢轴左侧是否至少有k个元素。如果有,那么您知道可以忽略右侧分区中的元素。否则,您可以忽略左侧分区中的所有元素,因为您知道该元素将位于正确的分区中。

请注意,选择算法仅识别那些前10%的数字。如果你需要对它们进行排序,那么你必须对这些数字进行排序(但只有那些数字,其他90%可以被忽略)。

答案 1 :(得分:4)

ALGO-1: 选择排序将在O(n ^ 2)中运行。你做的第一次扫描(n-1)比较,第二次(n-2),n / 10时间(nn / 10),所以(n-1)+(n-2)+ ... +(nn / 10)=>为O(n ^ 2)

ALGO-2: 从堆中删除max元素是O(log n),因此要运行O(n log n),因为要删除n / 10个元素。

另一种可能的算法,虽然仍然是O(n log n),但我认为可能比Algo-2更好的是使用以下快速排序启发程序。

  1. 选择一个支点
  2. 扫描所有元素并将它们放入2个桶中的一个:小于枢轴(左桶)和大于枢轴(右桶)(n-1)比较的桶。按照就地交换的快速排序程序进行操作。
  3. 一个。右边桶的大小== n / 10:你完成了。

    湾右侧桶的大小> n / 10然后新列表是右边的存储桶,递归地转到第1步,显示新列表。

    ℃。铲斗的大小在右边< n / 10然后左边的新列表是桶,但你只想找到最大的n-n / 10-(右桶的大小)。使用新列表递归转到第1步。

答案 2 :(得分:2)

我会在数组上使用quicksort降序并获得前N / 10项。

答案 3 :(得分:2)

使用前n / 10个元素构造一个O(lnN)替换成本的堆。扫描剩余的数字与堆中的最小值进行比较。如果当前元素的值高于堆中的最小元素,则将其插入堆中并删除最少元素。在最坏的情况下,N个扫描项目的两次O(lnN)操作时间给出O(N ln N),这在时间上并不比排序更好,但是需要的存储量比排序所需的少,因此实际上可能更快(特别是如果N个元素不适合缓存但是n / 10会 - 渐近时间只对你在平面空间中的一个很重要。)

答案 4 :(得分:0)

最有效的算法是使用修改后的快速排序。

Quicksort首先选择一个“中间”值,然后将所有低于此值的值放在左侧,并将所有值放大到右侧。通常你会向下并递归地对两边进行排序,但如果左边的元素少于10%,你只需要对右边进行排序。

如果超过10%,那么你只需要对左侧进行排序,可能只需要对左侧进行排序。

这不会降低最佳O(N lg N)以下的复杂度,但它会降低常数因子并使其比明显的“快速排序然后选择前10个”方法更快。

答案 5 :(得分:0)

非常愚蠢的问题,只需使用任何排序算法对其进行排序,并采用前N / 10项。

Algo-2相当于使用heap-sort

执行此操作

答案 6 :(得分:0)

因为这是家庭作业,我的答案是任何排序算法, 这是因为你无法在O(n * log(n))下解决这个问题。

如果可以,那么你可以在O(n * log(n))下完全排序数组。 (通过查找要完全排序的数组中排序的前10%,删除它们并重复此过程10次)。

因为在O(n * log(n))下无法进行排序,所以这个问题也是如此。

答案 7 :(得分:-1)

如果你知道N,只需创建一个长度为1/10的数组。每个单元格的初始值是Int.MinValue。检查数组中的每个数字。如果它大于10%数组中的最小数字,请添加它。

避免排序但以牺牲对答案数组的恒定扫描为代价。你可以通过保持排序顺序来抵消这一点,因此你可以使用二进制搜索。