задачка (программистское)
Jan. 5th, 2011 04:08 pmЗадачка для программистов и интересующихся. Наверняка известная, но мне в такой форме не встречалась, и понравилась.
Дан массив размером N, в нем есть только числа от 1 до N-1 (необязательно все, необязательно по порядку). Очевидно, какие-то из них повторяются. Найти какое-то число, которое встречается в массиве больше одного раза.
Суть в том, чтобы сделать это с как можно лучшей сложностью времени и места. Скажем, тривиально сделать это за O(N) времени с O(N) места. Можно лучше. Исходный массив не бесплатный: его можно менять, но это считается в бюджет места.
Update: все скрытые комментарии с правильными решениями раскрываются. Не заглядывайте в комментарии, если хотите дальше думать сами - там есть много правильных решений. Оптимальное решение этой проблемы выполняет задачу за O(N) времени, O(1) места.
Дан массив размером N, в нем есть только числа от 1 до N-1 (необязательно все, необязательно по порядку). Очевидно, какие-то из них повторяются. Найти какое-то число, которое встречается в массиве больше одного раза.
Суть в том, чтобы сделать это с как можно лучшей сложностью времени и места. Скажем, тривиально сделать это за O(N) времени с O(N) места. Можно лучше. Исходный массив не бесплатный: его можно менять, но это считается в бюджет места.
Update: все скрытые комментарии с правильными решениями раскрываются. Не заглядывайте в комментарии, если хотите дальше думать сами - там есть много правильных решений. Оптимальное решение этой проблемы выполняет задачу за O(N) времени, O(1) места.
no subject
Date: 2011-01-05 02:44 pm (UTC)no subject
Date: 2011-01-05 02:54 pm (UTC)no subject
Date: 2011-01-05 02:55 pm (UTC)no subject
Date: 2011-01-05 02:55 pm (UTC)no subject
Date: 2011-01-05 03:01 pm (UTC)Я его заскриню пока.
no subject
Date: 2011-01-05 03:03 pm (UTC)а идея похожа на предложенную ниже
no subject
Date: 2011-01-05 03:04 pm (UTC)Тривиальное не-решение:
Date: 2011-01-05 03:16 pm (UTC)for(i = 0; i < N; i++)
{
Q = 1 << arr[i];
if( N & P )
{
// Нашли дупликат
return i;
}
else
{
N &= P;
}
}
(понятно, что P всё равно должна быть размером O(N)).
Re: Тривиальное не-решение:
Date: 2011-01-05 03:18 pm (UTC)no subject
Date: 2011-01-05 03:22 pm (UTC)Но, конечно, O(N) времени и O(1) места - лучшее, что может быть.
no subject
Date: 2011-01-05 03:25 pm (UTC)no subject
Date: 2011-01-05 03:31 pm (UTC)понятное дело, в любом из этих списков есть цикл, причем длины меньше N. то есть есть элемент, на который указывают два указателя — последний в цикле и тот, что перед первым. эти два и будут повторяющимися элементами. а находить циклы в связных списках мы, слава заратустре, умеем (еще одна задача с интервью, пускаем два указателя с разными скоростями). чтобы не начать случайно изнутри цикла, начнем с последнего элемента, на него точно ничего не указывает.
итого О(1) памяти, O(N) времени. быстрее нельзя.
no subject
Date: 2011-01-05 03:40 pm (UTC)no subject
Date: 2011-01-05 03:48 pm (UTC)У нее есть еще один вариант посложнее. В массиве все числа встречаются по три раза, кроме одного, которое встречается либо один раз, либо два. Найти его как можно быстрее.
no subject
Date: 2011-01-05 03:49 pm (UTC)no subject
Date: 2011-01-05 03:52 pm (UTC)int index, int tmp,
index = 0;
tmp = A[index];
while( index != tmp ){
index = tmp;
tmp = A[index];
}
return tmp;
}
no subject
Date: 2011-01-05 03:54 pm (UTC)no subject
Date: 2011-01-05 04:03 pm (UTC)Вторая версия.
int f(int A[N]){
int index, int tmp,
index = 0;
tmp = A[index];
while( index != tmp ){
A[index] = index; // добавленная строка
index = tmp;
tmp = A[index];
}
return tmp;
}
no subject
Date: 2011-01-05 04:11 pm (UTC)no subject
Date: 2011-01-05 04:12 pm (UTC)Третий вариант.
int f(int A[N]){
int index, next_index;
index = A[0];
while( index != A[index] ){
next_index = A[index];
A[index] = index;
index = next_index;
}
return A[index];
}
no subject
Date: 2011-01-05 04:13 pm (UTC)За один проход, с одной переменной
Date: 2011-01-05 04:19 pm (UTC)При этом гарантированно находим число которое встречается чаще всего, что ещё круче чем исходное условие.
Ну и ещё и алгоритм - проще некуда
Человек который его придумал - гений.
no subject
Date: 2011-01-05 04:21 pm (UTC)no subject
Date: 2011-01-05 04:26 pm (UTC)Re: За один проход, с одной переменной
Date: 2011-01-05 04:28 pm (UTC)