合并两个大小为n和m的排序数组的时间复杂度

时间:2012-06-14 18:31:19

标签: complexity-theory

我只是想知道合并两个大小为n和m的排序数组的时间复杂性,因为 n总是大于m

我正在考虑使用合并排序,我假设在这种情况下会消耗O(log n + m)。

我不太喜欢大哦和东西。请告诉我这个问题的时间复杂性,如果有一种解决问题的优化方法,请告诉我。

提前致谢。

3 个答案:

答案 0 :(得分:27)

合并两个排序列表的时间绝对不是O(m log n)。它是O(n + m)。

代码看起来像这样:

allocate c with length n+m
i = 1
j = 1
while i < n or j < m
  if i = n
    copy rest of b into c 
    break    
  if j = m
    copy rest of a into c
    break
  if a[i] < b[j]
    copy a[i] into c
    i=i+1
    continue
  if b[j] < a[i]
    copy b[j] into c
    j=j+1
    continue

现在,如果我们没有足够的内存来分配c,那么可以将其修改为O(n + m)时间,因为大多数硬件(例如RAM和硬盘)都允许进行块操作。当我们需要将单个项目插入到数组的中间时,将一个块的尾端移动到一个以便腾出空间是一个单独的操作。如果您使用的硬件不允许这样,那么每个插入可能有O(n),这将是O(n + mn)复杂度。因为我们只需要将较小数组的元素插入到较大的数组中,所以当来自那个元素的元素已经在正确的位置时,我们永远不需要移动较大数组的片段。因此,n保持不变并且m位的复杂性增加。当具有长度为m的所有阵列b正确地放置在长度为n的阵列a的前面时,这是最坏的情况。

答案 1 :(得分:3)

我自己来解决这个问题,大O不是O(m+n),实际上只是O(n)

这是使用伪代码的原因: (注意::我编写了这段代码来处理 m> n m == n 的情况)

Merging sorted arrays A and B into C.
let ints 'i' and 'j' and 'k' = 0

while(i < A.length && j < B.length){
    if(A[i] < B[j]){
        C[k] = A[i]
        i++
    } else {
        C[k] = B[j]
        j++
    }
    k++
}

// Copies rest of A into C if A.len > B.len
while(i < A.length){ 
    C[k] = A[i]
    k++
    i++
}

// Copies rest of B into C if A.len < B.len
while(j < B.length){ 
    C[k] = B[j]
    k++
    j++
}
return C

现在我们所知道的是长度为 n 的数组大于长度为 m 的数组。这意味着即使 n> m m 的每个元素都可能大于长度为 n 的每个元素。 >(例如A[2,3,4,5,6]B[7,8,9]),我们不知道,这没关系。第一个循环将重复进行,直到ij等于它们各自数组的长度为止,然后接下来的两个while循环中只有一个循环将运行,直到将A或B的其余部分添加到C。

因此可以看出您以O(m+n)结尾,但是,Big O通常会处理最坏情况下的运行时,因此我们知道我们将遍历长度为<无论数组内部元素的构成如何,strong> n 次要比 m 次多,因此 m 总是小于 n 。因此,我们将 m 删除即可获得O(n)

这是因为 n 可能等于 infinity ,因此由于这是一种可能性,所以我们知道 m 永远不可能 infinity ,并且根据定义必须小于infinity ,因此,根据进一步的定义,常数小于n (因为它停止增长到无限大,因为只有 n 可以无限大)。而且由于在确定Big O运行时时会删除常量,因此得到O(n)

很显然,我参加晚会已经晚了几年,但是我希望这为将来可能遇到的其他任何人清除气氛:)

答案 2 :(得分:-10)

<强>注意!此答案包含错误

存在一种更有效的算法,并在另一个答案中提出。


复杂度为O(m log n)。

让长数组称为a,短数组为b,然后您描述的算法可以写成

  for each x in b
      insert x into a

循环有m次迭代。每次插入排序数组都是O(log n)操作。因此总体复杂度为O(m log n)。

由于b已排序,因此可以提高上述算法的效率

  for q from 1 to m
      if q == 1 then insert b[q] into a
      else 
         insert b[q] into a starting from the position of b[q-1]

这可以提供更好的渐近复杂度吗?不是真的。

假设来自b的元素均匀分布在a上。然后,每次插入都需要O(log (n/m)),整体复杂度为O(m log(n/m) )。如果存在一个不依赖于k>1n的常数m,那么n > k * m然后O(log(n/m)) = O(log(n)),我们会得到与上述相同的渐近复杂度。< / p>