我们内部有1000000个元素的数组,我们需要找到100倍的某个值。 有两种选择:首先-使用堆排序对其进行排序,然后通过二进制搜索进行搜索,其次-顺序搜索。
如果不计算,我会说第一种选择更好,但是...
在第二种选择中,在最坏的情况下,我们有num_of_elem * num_of_search = 100 * 1000000
,在第一种情况中,我们有(heapsort为O(nlogn)),所以(1000000*log(1000000))*100*log(1000000) = 1000000*20*100*20
。这意味着第二种选择要好400倍。
我在这里纠正吗?
答案 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 n
和n log n = O(kn)
,并且搜索之前的排序速度更快(渐近)。
这意味着您可以对某个常量k < c log n
使用类型为c
的某些测试,如果测试成功,则使用线性搜索方法,否则使用sort + search方法。再次由于运行时间是渐近的,必须使用测试和基准来定义c
的确切值。
奖励
如果您事先知道所有k
值,则可以使用另一种有趣的算法。假设A
是您要搜索的n
数字,而B
是您要搜索的k
数字。
B
(O(k log k)
时间)A
进行迭代,然后对每个元素e
在B
中进行二进制搜索,以获取e
(总共O(n log k)
时间)通过这种方式,您将确定B
中的哪些数字也位于A
中,并且将花费O(n log k + k log k)
,这在渐近上比其他两种方法都快(或快)如果k = O(n)
(例如,如果k < n
)。