Algorithm 数组合并与排序复杂度计算
我在我的算法课本上有一个练习,我对解决方案不是很确定。我需要解释此解决方案的原因:Algorithm 数组合并与排序复杂度计算,algorithm,sorting,merge,Algorithm,Sorting,Merge,我在我的算法课本上有一个练习,我对解决方案不是很确定。我需要解释此解决方案的原因: function array_merge_sorted(array $foo, array $bar) { $baz = array_merge($foo, $bar); $baz = array_unique($baz); sort($baz); return $baz; } 合并两个数组并对它们进行排序并不是最有效的,我需要提供一个最优化的解决方案,并证明不能提供更好的解决方案 我的想法是
function array_merge_sorted(array $foo, array $bar)
{
$baz = array_merge($foo, $bar);
$baz = array_unique($baz);
sort($baz);
return $baz;
}
合并两个数组并对它们进行排序并不是最有效的,我需要提供一个最优化的解决方案,并证明不能提供更好的解决方案
我的想法是使用一个mergesort算法,即O(nlogn),将作为参数传递的两个数组合并并排序。但是我怎样才能证明这是有史以来最好的解决方案呢?算法
正如您所说,两个输入都已排序,您可以使用一种简单的类似拉链的方法
每个输入数组都有一个指针,指向数组的开头。然后比较两个元素,将较小的元素添加到结果中,并使用较小的元素推进数组指针。然后重复该步骤,直到两个指针都到达末尾,并且所有元素都添加到结果中
您可以在中找到一组这样的算法,我当前介绍的方法被列为“合并两个列表”
下面是一些伪代码:
函数数组合并排序(数组第一,数组第二){
数组结果=新数组(first.length+second.length);
int firstPointer=0;
int secondPointer=0;
while(firstPointer
证明 该算法显然在
O(n)
中工作,其中n
是结果列表的大小。或者更精确地说,它是O(max(n,n')
,其中n
是第一个列表的大小,而n'
是第二个列表的大小(或者O(n+n')
,是同一组)
这显然也是最佳的,因为在某一点上,您需要至少遍历所有元素一次,以构建结果并知道最终顺序。这会产生该问题的Omega(n)
下限,因此该算法是最佳的
一个更正式的证明假设一个更好的任意算法
A
,它解决了问题,而不至少查看每个元素(或者更精确,小于O(n)
)
我们把算法没有看到的元素称为e
。我们现在可以构造一个输入I
,这样e
就有一个值,该值在它自己的数组中满足顺序,但会被算法错误地放在结果数组中
我们能够为每个算法A
这样做,并且由于A
总是需要在所有可能的输入上正确工作,因此我们能够找到一个反例I
,使其失败
因此,A
不可能存在,Omega(n)
是该问题的下限
为什么给定的算法更差 您给定的算法首先合并两个数组,这在
O(n)
中起作用,这很好。但是在这之后它对数组进行排序
排序(更精确:基于比较的排序)的下限为Omega(n logn)
。这意味着每种算法都不可能比这更好
因此,给定算法的总时间复杂度为O(n logn)
(因为排序部分)。这比O(n)
更差,其他算法的复杂度和最优解也更差
然而,为了超级正确,我们还需要讨论排序-方法是否真的会产生这种复杂性,因为它不会获得任意输入,而是总是合并-方法的结果。因此,可能特定的排序方法对这种特定的inpu特别有效ts,最终产生
O(n)
但我怀疑这是否是您任务的重点。
正如您所说,两个输入都已排序,您可以使用一种简单的类似拉链的方法
每个输入数组都有一个指针,指向数组的开头。然后比较两个元素,将较小的元素添加到结果中,并将数组的指针与较小的元素一起前进。然后重复该步骤,直到两个指针都到达末尾,并将所有元素添加到结果中
您可以在中找到一组这样的算法,我当前介绍的方法被列为“合并两个列表”
下面是一些伪代码:
函数数组合并排序(数组第一,数组第二){
数组结果=新数组(first.length+second.length);
int firstPointer=0;
int secondPointer=0;
while(firstPointer
证明 该算法显然在
O(n)
中工作,其中n
是结果列表的大小。或者更精确地说,它是O(max(n,n')
,其中n
是第一个列表的大小,而n'
是第二个列表的大小(或者O(n+n')
,是同一组)
这显然也是op
function Array<Element> mergeSorted(Array<Element> first, Array<Element> second) {
Array<Element> result = new Array<Element>(first.length + second.length);
int firstPointer = 0;
int secondPointer = 0;
while (firstPointer < first.length && secondPointer < first.length) {
Element elementOfFirst = first.get(firstPointer);
Element elementOfSecond = second.get(secondPointer);
if (elementOfFirst < elementOfSecond) {
result.add(elementOfFirst);
firstPointer = firstPointer + 1;
} else {
result.add(elementOfSecond);
secondPointer = secondPointer + 1;
}
}
}