为什么mergesort O(log n)?


27

Mergesort是分治法,是O(log n),因为输入被反复减半。但是它不应该是O(n),因为即使每个循环的输入减半,每个输入项也需要迭代以在每个减半的数组中进行交换?在我看来,这本质上是渐近O(n)。如果可能,请提供示例并说明如何正确计算操作!我还没有编码任何东西,但是我一直在网上寻找算法。我还附上了Wikipedia用来直观地显示mergesort如何工作的gif图像。

在此处输入图片说明


33
是O(n log n)
Esben Skov Pedersen

18
即使是上帝的排序算法(一种假设的排序算法,该算法也可以访问告诉其每个元素所属位置的oracle)也具有O(n)的运行时间,因为它需要将处于错误位置的每个元素至少移动一次。
Philipp 2015年

Answers:


59

它是O(n * log(n)),而不是O(log(n))。正如您准确地推测的那样,必须迭代整个输入,并且该输入必须发生O(log(n))次(输入只能减半O(log(n))次)。n个项目重复log(n)次得到O(n log(n))。

已经证明,没有任何一种比较排序可以比这更快地运行。只有依靠输入的特殊属性的排序(例如基数排序)才能克服这种复杂性。虽然mergesort的常数因子通常不是那么大,所以复杂性较差的算法通常会花费较少的时间。


3
S /快/低复杂度/
JK。

33

合并排序的复杂度为O(nlogn)而不是O(logn)。

合并排序是一种分而治之的算法。从3个步骤来思考-

  1. 除法步骤计算每个子阵列的中点。每个步骤仅需O(1)时间。
  2. 征服步骤以递归方式对两个子数组进行排序,每个子数组包含n / 2个元素(对于偶数n个元素)。
  3. 合并步骤合并需要O(n)时间的n个元素。

现在,对于第1步和第3步,即在O(1)和O(n)之间,O(n)更高。让我们考虑步骤1和3总共花费O(n)的时间。假设某个常数c为cn。

这些步骤执行了多少次?

为此,请看下面的树-从上到下的每个级别,级别2调用2个长度为n / 2的子数组上的merge方法。这里的复杂度是2 *(cn / 2)= cn级别3在每个长度为n / 4的4个子数组上调用merge方法。这里的复杂度是4 *(cn / 4)= cn,依此类推...

现在,对于给定的n,这棵树的高度为(logn + 1)。因此,总体复杂度为(logn + 1)*(cn)。合并排序算法为O(nlogn)。

合并n个元素的排序

图片来源:可汗学院


9

合并排序是一种递归算法,时间复杂度可以表示为以下递归关系。

T(n)= 2T(n / 2)+ɵ(n)

可以使用“递归树”方法或“主”方法解决以上重复问题。属于主方法的情况II,并且递归的解决方案是ɵ(n log n)。

在所有3种情况下(最差,平均和最佳),合并排序的时间复杂度为ɵ(nLogn),因为合并排序始终将数组分为两半,并花费线性时间来合并两半。

它将输入数组分为两半,将自己称为两半,然后合并两个排序的两半。merg()函数用于合并两个半部分。merge(arr,l,m,r)是假设arr [l..m]和arr [m + 1..r]已排序并将两个排序后的子数组合并为一个的关键过程。有关详细信息,请参见以下C实现。

MergeSort(arr[], l,  r)
If r > l
     1. Find the middle point to divide the array into two halves:  
             middle m = (l+r)/2
     2. Call mergeSort for first half:   
             Call mergeSort(arr, l, m)
     3. Call mergeSort for second half:
             Call mergeSort(arr, m+1, r)
     4. Merge the two halves sorted in step 2 and 3:
             Call merge(arr, l, m, r)

在此处输入图片说明

如果我们仔细观察一下该图,我们可以看到将数组递归地分为两半,直到大小变为1。一旦大小变为1,合并过程就开始起作用,并开始合并数组直到完整的数组成为合并。


1
您能否详细说明合并部分的性质以及它对O(n log n)性能的影响?

合并函数的复杂度为O(n),因为它需要2个数组作为输入,将它们进行比较并以新的形式给出输出。由于将数组中的每个元素与每个其他元素进行比较,因此此合并函数的复杂度为O(n)。
Nishant sethi

1
我喜欢这种可视化效果!
spaaarky21

0

基于比较的排序算法具有下限𝞨(n*log(n)),这意味着不可能具有O(log(n))时间复杂度的基于比较的排序算法。

顺便说一句,合并排序是O(n*log(n))。这样想吧。

[ a1,a2,         a3,a4,         a5,a6,          a7,a8     .... an-3,an-2,     an-1, an ] 
   \ /            \  /           \ /             \  /            \  /            \  /    
    a1'            a3'            a5'             a7'            an-3'           an-1'    
      \            /                \             /                 \             /
            a1''                          a5''                       an-3''
             \                             /                         /
                          a1'''                                     /
                           \
                                              a1''''

这看起来是反向的二叉树。

让输入大小为n

每个a_n代表一个元素列表。第一行a_n只有一个元素。

在每个级别,平均合并成本之和为n(存在成本较低的极端情况[1])。树的高度是log_2(n)

因此,合并排序的时间复杂度为O(n*log_2(n))

[1]如果在已经排序的列表上排序,这被称为最佳情况。成本降低到了n/2 + n/4 + n/8 + .... + 1 = 2^log_2(n) -1 ~ O(n)。(假设长度n是二的幂)


-2

排序是计算机科学中的NP-完全问题(非多项式问题)。这意味着,除非经过数学证明,否则在对元素列表进行排序时不能低于O(n log n)。

在Wikipedia中查看此文章(https://en.wikipedia.org/wiki/P_versus_NP_problem

到目前为止,基本上没有人能够证明(P == NP),如果这样做,您首先会成为百万富翁,其次您将能够打破所有使用的发布/私有密钥安全机制,从而引发第三次世界大战如今无处不在:)


2
那不是NP的意思。甚至BubbleSort都在P中。您必须努力做出不在P中的排序(例如BogoSort)
Caleth
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.