【问题标题】:Find the duplicate element in an array of consecutive integers in O(log n) time在 O(log n) 时间内找到连续整数数组中的重复元素
【发布时间】:2014-12-28 06:21:02
【问题描述】:

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

这种情况有些具体,因为总共有 11 个整数(1 到 10,按此顺序)加上,其中任何一个数字的一​​个副本,插入在两者之间的某个位置。

给了我一个类似这样的样本:

{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) 标准?而且,是否有任何替代/改进?

【问题讨论】:

  • 提示:始终使用半开区间。顺便说一句:elseif-brnch 中的那些神奇数字呢?

标签: c arrays algorithm optimization duplicates


【解决方案1】:

是的,它具有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)

【讨论】:

    【解决方案2】:

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

    仔细查看数据,我们可以很容易地看到,在连续元素数组中的随机位置(比如index)插入重复元素后,元素的属性将发生变化(a[i] == i+1 --> 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]);
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-03
      • 1970-01-01
      • 1970-01-01
      • 2017-01-26
      • 2020-01-22
      • 2012-04-16
      • 2011-11-28
      相关资源
      最近更新 更多