我有一系列n个坚果和一系列n个螺栓,两者都按照不断增加的尺寸排列。我需要给出一个O(n)算法来检查是否 螺母和螺栓具有相同的尺寸。坚果大小在阵列NUTS [1..n] 螺栓尺寸在数组BOLTS [1 ... n]
中我不需要找到所有匹配项,即使找到一个匹配项也只需停止算法即可。这是我的伪代码到目前为止的样子
for each n in NUTS
for each b in BOLTS
if BOLTS[i] == NUTS[i]
break;
因此,对于每个坚果,我都在搜索所有螺栓。这是O(n ^ 2),我怎么做这个O(n)?我的理解是我可能只需要一个for循环就可以做到这一点。对不起,我的理解有点不稳定
答案 0 :(得分:2)
您可以在同一循环中单步执行两个数组,但使用两个单独的索引变量。您总是递增数组值较小的索引变量。如果两者都不小,那么它们相等,你就找到了匹配。
i = 0;
j = 0;
while (i < n and j < n) {
if (NUTS[i] < BOLTS[j]) {
i++;
} else if (NUTS[i] > BOLTS[j]) {
j++;
} else {
return true; // found a match
}
}
return false; // found nothing
最好的情况是NUTS[0] == BOLTS[0]
,因为您输入最后的else
子句并立即返回true
。
最糟糕的情况是你从未输入最后的else
子句,因为那时你必须一直迭代循环到最后。如果您始终采用第一个或第二个if
子句,增加i
或j
,则会发生这种情况。在最糟糕的情况下,您可以在递增i
和j
之间切换,使两者都尽可能慢地增长。在至少一个变量超过2*n
之前,这会导致n
步骤的最坏情况。
因此该算法在O(2 * n)中,即O(n)。
答案 1 :(得分:1)
在最坏的情况下,伪代码共享将采用O(n ^ 2),即没有匹配对时。 但是,您可以使用二进制搜索将其加速到O(nlogn),因为数组按排序顺序。
foreach A in nuts:
if binarysearch ( Bolts, Bolts+n , A)
break;
此外,您可以使用每个数组中的两个指针将其加速到O(n)并相应地递增它们。
Bolt_index = Nut_index = 0
while ( Bolt_Index < Bolts.size && Nut_Index < Nuts.Size)
while( Bolt_Index < Bolts.Size && Bolts[Bolt_index] < Nuts[Nut_Index] )
Bolt_index++ ;
while( Nut_Index < Nuts.Size && Nuts[Nut_index] < Bolts[Bolt_Index] )
Nut_index++ ;
if Bolt_Index< Bolts.Size && Nut_Index < Nuts.Size && Bolts[Bolt_Index] == Nuts[Nut_Index]
Match_found// break
else
Nut_Index++ // increment either Nut_Index or Bolt_Index