在寻找元素之前是否值得对数组进行排序?

时间:2019-07-08 05:13:51

标签: algorithm performance sorting

我们内部有1000000个元素的数组,我们需要找到100倍的某个值。 有两种选择:首先-使用堆排序对其进行排序,然后通过二进制搜索进行搜索,其次-顺序搜索。

如果不计算,我会说第一种选择更好,但是... 在第二种选择中,在最坏的情况下,我们有num_of_elem * num_of_search = 100 * 1000000,在第一种情况中,我们有(heapsort为O(nlogn)),所以(1000000*log(1000000))*100*log(1000000) = 1000000*20*100*20。这意味着第二种选择要好400倍。

我在这里纠正吗?

1 个答案:

答案 0 :(得分:2)

请记住,使用O标记指定算法的运行时间时, “渐近”。过于简化,运行时间O(log n)意味着您的程序执行了c*log n个步骤,其中c是您实际上不知道的某个常数。可能会很大。因此,在运行时间的公式中使用实数将不会为您提供准确的结果。

以下是找到问题答案的两种方法:

  • 您可以针对不同的输入运行一堆测试,以比较这两种方法。选择最适合您的应用程序的方式。

  • 您可以进行更深入的理论分析:

假设您要搜索的数组中有n个元素,    并且您想找到k个元素。因此,在您的示例中,n = 1000000    和k = 100

如果您对每个元素进行排序并使用二进制搜索,    您将O(n log n)时间用于排序,将O(k log n)时间用于    搜索,总共O(n log n + k log n)。如果你做线性    搜索k个元素中的每一个,您将花费O(kn)时间。

现在,如果k = O(log n),则O(kn)变成O(n log n),并使用两种方法    应该同样快(渐近)。但是,如果k = Omega(log n)(即k是    从下到上依次为log nn log n = O(kn),并且搜索之前的排序速度更快(渐近)。

这意味着您可以对某个常量k < c log n使用类型为c的某些测试,如果测试成功,则使用线性搜索方法,否则使用sort + search方法。再次由于运行时间是渐近的,必须使用测试和基准来定义c的确切值。

奖励

如果您事先知道所有k值,则可以使用另一种有趣的算法。假设A是您要搜索的n数字,而B是您要搜索的k数字。

  • 排序BO(k log k)时间)
  • A进行迭代,然后对每个元素eB中进行二进制搜索,以获取e(总共O(n log k)时间)

通过这种方式,您将确定B中的哪些数字也位于A中,并且将花费O(n log k + k log k),这在渐近上比其他两种方法都快(或快)如果k = O(n)(例如,如果k < n)。