今天,一位采访者问我这个问题。我的直接反应是我们可以简单地进行线性搜索,将当前元素与数组中的前一个元素进行比较。然后他问我如何在不太线性的时间内解决问题。
假设
[0, n]
,其中n
是数组的长度。示例数组:[0,1,2,3,4,5,6,7,8,8,9]
我试图想出一个分而治之的算法来解决这个问题,但我不相信这是正确的答案。有没有人有任何想法?
答案 0 :(得分:25)
可以使用修改后的二进制搜索在O(log N)中完成:
从数组中间开始:如果array [idx]< idx副本位于左侧,否则位于右侧。冲洗并重复。
答案 1 :(得分:7)
如果数组中没有数字丢失,如示例所示,它可以在O(log n)中使用二进制搜索。如果a[i] < i
,则副本位于i
之前,否则位于i
之后。
如果缺少一个号码且一个号码重复,我们仍然知道如果a[i] < i
副本必须在i
之前且a[i] > i
之前,则缺席号码必须在{{1}之前和之后的重复。但是,如果i
,我们不知道在a[i] == i
之前或i
之后是否都缺少数字和重复。在这种情况下,我没有看到子线性算法的方法。
答案 2 :(得分:6)
我试图想出一个分而治之的算法来解决这个问题,但我不相信这是正确的答案。
当然,你可以进行二分搜索。
如果arr[i/2] >= i/2
,则副本位于数组的上半部分,否则它位于下半部分。
while (lower != upper)
mid = (lower + upper) / 2
if (arr[mid] >= mid)
lower = mid
else
upper = mid-1
由于lower
和upper
之间的数组在每次迭代中减半,因此算法在O(log n)中运行。
答案 3 :(得分:1)
给定数组元素之和与0到n-1个自然数之和的差异为您提供了重复元素。 0到n-1个元素的和是(N * N-1)/ 2 示例数组是[0,1,2,3,4,5,6,7,8,8,9] 0到9个自然数的总和是:45 给定数组元素的总和:53 53-45 = 8哪个是重复元素
答案 4 :(得分:0)
示例数组与您的问题略有不同。由于n是数组的长度,并且在数组中只有一个副本,因此数组中每个元素的值应该在[0,n-1]中。
如果确实如此,则此问题与How to find a duplicate element in an array of shuffled consecutive integers?
相同以下代码应在O(n)时间和O(1)空间中找到副本。
public static int findOnlyDuplicateFromArray(int[] a, boolean startWithZero){
int xor = 0;
int offset = 1;
for(int i=0; i < a.length; i++){
if(startWithZero)
xor = xor ^ (a[i] + offset) ^ i;
else
xor = xor ^ a[i] ^ i;
}
if(startWithZero)
xor = xor - offset;
return xor;
}
答案 5 :(得分:0)
怎么样? (递归式)
public static int DuplicateBinaryFind(int[] arr, int left, int right)
{
int dup =0;
if(left==right)
{
dup = left;
}
else
{
int middle = (left+right)\2;
if(arr[middle]<middle)
{
dup = DuplicateBinaryFind(arr,left, middle-1);
}
else
{
dup = DuplicateBinaryFind(arr, middle+1, right);
}
}
return dup;
}
答案 6 :(得分:0)
#include <bits/stdc++.h>
using namespace std;
int find_only_repeating_element(int arr[] , int n){
int low = 0;
int high = n-1;
while(low <= high){
int mid = low + (high - low)/2;
if(arr[mid] == arr[mid + 1] || arr[mid] == arr[mid - 1]){
return arr[mid];
}
if(arr[mid] < mid + 1){
high = mid - 2;
}else{
low = mid + 1;
}
}
return -1;
}
int main(int argc, char const *argv[])
{
int n , *arr;
cin >> n;
arr = new int[n];
for(int i = 0 ; i < n ; i++){
cin >> arr[i];
}
cout << find_only_repeating_element(arr , n) << endl;
return 0;
}