我只是想知道合并两个大小为n和m的排序数组的时间复杂性,因为 n总是大于m 。
我正在考虑使用合并排序,我假设在这种情况下会消耗O(log n + m)。
我不太喜欢大哦和东西。请告诉我这个问题的时间复杂性,如果有一种解决问题的优化方法,请告诉我。
提前致谢。
答案 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]
),我们不知道,这没关系。第一个循环将重复进行,直到i
或j
等于它们各自数组的长度为止,然后接下来的两个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>1
或n
的常数m
,那么n > k * m
然后O(log(n/m)) = O(log(n))
,我们会得到与上述相同的渐近复杂度。< / p>