在O(log n)时间内查找连续整数数组中的重复元素

时间:2014-10-31 20:34:29

标签: c arrays algorithm optimization duplicates

几天前,我在一次采访中被要求提供一个程序,该程序将在O(log n)时间内在连续的整数数组中找到单个重复元素。

这种情况有点具体,因为总共有11个整数(1到10,按顺序)加上,这些数字中的任何一个的单个副本插入其间。< / p>

我得到了一个与此相似的样本:

  

{1,2,3,4,5,6, 2 ,7,8,9,10}

所以,现在我想出了以下C代码:

#include <stdio.h>

int main (void)
{
    int a[11] = {1, 2, 3, 4, 5, 6, 2, 7, 8, 9, 10}, first=0, last=10, mid;

    while (1)
    {
        mid = (first + last)/2;

        if (mid+1 == a[mid])
            first = mid+1;

        else if ((mid == 0) || (mid == 10) || (a[mid+1] - a[mid-1] == 1))   /* Order is Important, (a[mid+1] - a[mid-1] == 1) must be last */
            break;

        else
            last = mid-1;
    }

    printf("Duplicate element is %d, located at position no. %d.", a[mid], mid+1);

    return 0;
}

这是否符合O(log n)标准?并且,有没有替代/改进?

2 个答案:

答案 0 :(得分:3)

是的,时间复杂度O(log n)

使用以下事实可以使代码更清晰:您需要找到i这样的最小a[i] != i + 1,因此可以更简洁的方式实现:

//invariant: the [0...low] prefix does not contain a duplicate
//           the [0...high] prefix contains a duplicate
low = 0 //[0...0] prefix obviously does not contain a duplicate
high = 10 //the entire array obviously contains a duplicate
while high - low > 1:
    mid = (low + high) / 2 
    if a[mid] != mid + 1:
        high = mid
    else:
        low = mid
print(a[high], high)

答案 1 :(得分:1)

我们可以修改binary search algorithm以获得解决方案。在binary search中,我们有一个键,我们使用此键通过平分数组大小来找到它的位置。在这里,我们没有钥匙,相反,我们必须找到它。但duplicate element的行为可用于bisect数组大小。怎么样 ?让我们看看:

仔细查看数据后,我们可以很容易地看到,在连续元素数组中的随机位置(比如index)插入重复元素后,元素的属性将发生变化(a[i] == i+1 - &gt;来自a[i] != i+1位置的index}(包括index)。现在,此更改的属性可用于平分数组大小。因此,我们可以在O(log(n))中找到副本。

例如,考虑您给定的数组:{1, 2, 3, 4, 5, 6, 2, 7, 8, 9, 10}

{1,  2,  3,   4,  5,  6,  2,  7,  8,  9,  10}
                          ||
                          from this position the the property of (a[i] == i+1) will no more satisfied.

此属性可以是用于在解决方案中平分数组大小的模型。

void  binary_duplictae_finder(int a[], int low, int high) {

   int mid=(low+high)/2;

   if(high - low > 1){
          if(a[mid]!=mid+1)
              binary_duplictae_finder(a, low, mid);
          else
              binary_duplictae_finder(a, mid, high);
   }

   if(high==low+1)
      printf("%d ", a[high]);
 }