排序算法与简单迭代

时间:2016-04-28 00:05:43

标签: arrays algorithm sorting integer

我刚刚开始使用算法和排序,所以请耐心等待......

我们说我有一个50000整数的数组。 我需要选择最小的30000个 我想到了两种方法:
1.迭代整个数组并找到每个最小的整数
2.我首先对整个阵列进行排序,然后只选择第一个30000.

任何人都能告诉我它的区别是什么,哪种方法会更快,为什么? 如果阵列更小或更大怎么办?答案会改变吗?

4 个答案:

答案 0 :(得分:2)

选项1听起来像天真的解决方案。它将涉及通过数组来找到30000次最小的项目。每次找到最小的时候,可能会将该项交换到数组的开头或结尾。在基本术语中,这是 O(n ^ 2)复杂度。

所涉及的实际操作数量将小于 n ^ 2 ,因为 n 每次都会减少。所以你会有大约50000 + 49999 + 49998 + ... + 20001,这相当于超过10亿次(1000万次)迭代。

选项2将使用类似快速排序或类似的算法,通常 O(n.logn)

这里提供实际数据更难,因为一些有效的排序算法可能会出现 O(n ^ 2)的最坏情况。但是,假设您使用的是一个保证良好的 O(n.logn)。这将达到50000 * 15.61,约为78万。

所以很明显,在这种情况下,选项2获胜。

  

如果阵列更小或更大怎么办?答案会改变吗?

除非数组变得非常小,否则答案仍然是选项2.数组越大,选项2就越有利。这是时间复杂性的本质。 O(n ^ 2)的增长速度远远超过 O(n.logn)

一个更好的问题是“如果我想要更少的最小值,那么选项1何时变得更可取?”。虽然答案稍微复杂一些,因为有很多因素(比如选项1和选项2中的“一个操作”,以及内存访问模式等其他问题),你可以得到简单的答案直接来自时间复杂性。当要选择的最小值的数量低于 n.logn 时,选项1将变得更可取。对于50000元素数组,这意味着如果要选择15个或更少的最小元素,则选项1将获胜。

现在,考虑一个选项3,将数组转换为 min-heap 。构建堆是 O(n),从中删除一个项目是 O(logn)。您将删除30000项。所以你有建造成本加上搬迁费用:50000 + 30000 * 15.6 =约52万。这忽略了每次删除元素时 n 变小的事实。它仍然是 O(n.logn),就像选项2一样,但它可能更快:你没有费心去排序你不关心的元素,从而节省了时间。

我应该提到在所有三种情况下,结果将是按排序顺序的最小30000值。可能还有其他解决方案可以按特定顺序为您提供这些值。

答案 1 :(得分:2)

30k接近50k。只需对数组进行排序并获得最小的30k,例如Python:sorted(a)[:30000]。这是O(n * log n)操作。

如果您需要找到100个最小的项目(100 << 50k),那么heap可能更合适,例如,在Python中:heapq.nsmallest(100, a)。它是O(n * log k)

如果整数范围有限,您可以考虑O(n)排序方法,例如counting sort and radix sort

这里简单的迭代方法是O(n**2)(二次)。即使是一个约为一百万的温和n;对于线性算法,它导致~10**12操作比~10**6差得多。

答案 2 :(得分:2)

对于几乎所有实际目的而言,排序和获取前30,000可能是最好的。在大多数语言中,这是一行或两行代码。很难出错。

如果你有一个真正苛刻的应用程序,或者只是想摆弄,你可以使用selection algorithm找到第30,000个最大的数字。然后再通过数组将找到29,999个不大的。

有几种众所周知的选择算法只需要O(n)比较,而某些算法对于具有特定属性的数据则是亚线性的。

实践中最快的是QuickSelect,顾名思义,它的工作方式大致类似于部分QuickSort。不幸的是,如果数据的排序非常糟糕,QuickSelect可能需要O(n ^ 2)时间(就像QuickSort一样)。选择枢轴有各种技巧,使得几乎不可能获得最坏情况下的运行时间。

QuickSelect将以重新排序的数组结束,因此最小的30,000个元素位于第一部分(未排序),其次是其余部分。

由于标准选择算法是基于比较的,因此它们可以处理任何类型的可比数据,而不仅仅是整数。

答案 3 :(得分:0)

如果您的输入是整数,则可以使用基数排序或计数排序在潜在的O(N)时间内执行此操作。

另一种方法是通过quickselect获取第30000个最大整数,并简单地遍历原始数组。这具有Θ(N)时间复杂度,但在最坏的情况下具有O(N ^ 2)用于快速选择。