Ответ 1
Может быть выполнено в O (log N) с измененным двоичным поиском:
Начало в середине массива: если array [idx] < idx дубликат находится слева, в противном случае - вправо. Промыть и повторить.
Сегодня интервьюер задал мне этот вопрос. Мой немедленный ответ заключался в том, что мы могли просто выполнить линейный поиск, сравнивая текущий элемент с предыдущим элементом в массиве. Затем он спросил меня, как проблема может быть решена в менее чем линейное время.
Предположения
[0, n]
, где n
- длина массива.Пример массива: [0,1,2,3,4,5,6,7,8,8,9]
Я попытался придумать алгоритм разделения и покорения, чтобы решить эту проблему, но я не уверен, что это правильный ответ. У кого-нибудь есть идеи?
Может быть выполнено в O (log N) с измененным двоичным поиском:
Начало в середине массива: если array [idx] < idx дубликат находится слева, в противном случае - вправо. Промыть и повторить.
Если в массиве отсутствует число, как в примере, оно выполняется в O (log n) с двоичным поиском. Если a[i] < i
, дубликат перед i
, в противном случае - после i
.
Если есть один номер, отсутствующий и один дубликат, мы все же знаем, что если a[i] < i
дубликат должен быть до i
, а если a[i] > i
, отсутствующий номер должен быть до i
и дублировать после. Однако, если a[i] == i
, мы не знаем, остались ли недостающие числа и дубликаты до i
или оба после i
. В этом случае я не вижу пути для сублинейного алгоритма.
Я попытался придумать алгоритм разделения и покорения, чтобы решить эту проблему, но я не уверен, что это правильный ответ.
Конечно, вы можете выполнить двоичный поиск.
Если 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).
Разница между суммой заданных элементов массива и суммой натуральных чисел от 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 Кого является дублированный элемент
Пример массива немного отличается от вашего вопроса. Поскольку n - длина массива, и в массиве есть один и только дубликат, значение каждого элемента в массиве должно быть в [0, n-1].
Если это так, то этот вопрос тот же, что и Как найти дублирующий элемент в массиве перетасованных последовательных целых чисел?
Следующий код должен найти дубликат в 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;
}
Как насчет этого? (стиль рекурсии)
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;
}