分析一个O(n)算法来检查已排序数组中的螺母/螺栓匹配

时间:2017-04-16 18:23:06

标签: algorithm language-agnostic big-o

我有一系列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循环就可以做到这一点。对不起,我的理解有点不稳定

2 个答案:

答案 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子句,增加ij,则会发生这种情况。在最糟糕的情况下,您可以在递增ij之间切换,使两者都尽可能慢地增长。在至少一个变量超过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