几天前,我在一次采访中被要求提供一个程序,该程序将在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)
标准?并且,有没有替代/改进?
答案 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]);
}