LINUX.ORG.RU

Нахождение повторяющихся элементов в массиве

 


0

8

В ходе просмотра видеокурса по алгоритмам и структурам данных столкнулся с задачей, которая никак не уложится у меня в голове.

Постановка задачи: Дан массив из n+1 элементов, в котором записаны числа от 1 до n. Отсюда ясно, что в этом массиве будет повторы. Необходимо найти это самое повторяющееся число. Повторяться оно может произвольное число раз.

Ограничения:

1) Время работы алгоритма: O(n);

2) Расход памяти: O(1);

3) Массив не изменяемый(immutable).

Я могу придумать решения за O(n^2), решение с использованием дополнительной памяти за O(n), решение с изменяемым массивом за то же самое O(n). Больше идей нет.

Собственно вопрос к вам, уважаемые специалисты - а вы знаете решение этой задачи? Или же вы уверенны, что она не решается и способны привести доказательство этого факта? Само решение меня на данный момент не интересует, важно лишь подтверждение факта решаемости данной задачи. Ну или же было бы интересно какое либо простое замечание, которое далеко от полного алгоритма решения, но могло бы на него натолкнуть.

Ссылка на оригинал: Лекция №5. Время, с которого идет описание задачи: 00:09:10.

Ответ на: комментарий от ebantrop

Специально пересматривал видео - твой вариант вполне допустимый. Но при этом и определить надо любой повтор. То есть на твоем примере правильным ответом будет и 2 и 1.

TheKnight ★★★
() автор топика
Ответ на: комментарий от TheKnight

То есть на твоем примере правильным ответом будет и 2 и 1

Не понял. Повторится может любое число, но это число будет единственным? Иными словами ежели повторяется 1, то уже ни одно число повторным быть не может, правильно?

ebantrop
()
Ответ на: комментарий от ebantrop

Нет. Повториться может любое число. Но при этом быть единственным повтором оно не обязано. Хоть там каждое число пару иметь будет. И число повторов тоже не ограниченно.

TheKnight ★★★
() автор топика
Ответ на: комментарий от malbolge

По ссылке не ходил?) Предоставил специально для проверки записи мной условий)

TheKnight ★★★
() автор топика

Хочу спать. Придумал решение за O(n*log n)

Разбиваем множество возможных чисел на два интервала {1..a} и {a+1..n} по возможности равных( a=(n+1)/2 ). Первый интервал содержит a чисел, второй - n-a чисел.

Считаем, сколько встречается в массиве чисел из первого интервала и сколько из второго(на это требуется O(n) операций). Очевидно, что выполнится одно из условий:

1) В первый интервал попадет больше чем a чисел => в первом интервале гарантированно есть повтор

2) Во второй интервал попадет больше чем n-a чисел => во втором интервале есть повтор

Интервал и дальше разбивается на два до тех пор, пока в нем не останется одно искомое число.

Разбивать так нужно log n раз => O(n*log n)

Ничего лучше пока в голову не лезет

Waterlaz ★★★★★
()
Ответ на: комментарий от malbolge

Там все ОК: мало звезд — значит, новичок. Новичок — может быть спамер какой.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от PolarFox

И действительно.

Ну, а в общем виде (несколько повторов разных чисел) получается, что задача решения не имеет.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от malbolge

Виноват, не знал о такой.

Но тем не менее по условию задачи сортировка ни in situ, ни с выделением дополнительной памяти не подходит.

unlog1c ★★★
()

Надо XOR-ить элементы (на случай нечетного количества повторений), и считать сумму на случай четного. </thread>

johnson102
()

Можно представить элементы как направленный граф и искать цикл, для этого существуют экономные методы. Для поиска коллизий хеш-функций в общем случае так и делают. Но этот метод не будет работать, если начальный элемент — уже часть кратчайшего цикла, нужно будет начинать все с начала с другого элемента и т.д., т.е. все равно будет N^2 в худшем случае...

trycatch ★★★
()

решение с изменяемым массивом за то же самое O(n)

Что за решение? Как ни стыдно, но не могу сообразить.

trycatch ★★★
()
Ответ на: комментарий от TheKnight

Посмотрел видео. Там лектор отвечая на вопрос из зала оговаривает, что числа могут быть повторные любое количество раз, но найти надо только один повтор. То есть в примере A = [1 1 2 2] правильным ответом будет любое одно число или 1 или 2. Не обязательно все повторные находить.

Правда от этого не сильно легче.

ebantrop
()

с использованием флага переноса можно просто:

buf=0
массив x[1..n+1]

цикл:

buf=buf+2^x[i]

проверяем флаг переноса - если установлен, то число x[i] повторяется -> выход.

конец цикла.

памяти используется n бит. противоречит ли это условию или нет - не сразу ясно.

dikiy ★★☆☆☆
()
Последнее исправление: dikiy (всего исправлений: 1)
Ответ на: комментарий от dikiy

таки противоречит. Очевидно, что размер требуемой памяти O(n). Но кстати, и само условие неверно, ибо по большому счету размер памяти как минимум O(log n) бит. Так как именно столько надо, чтоб хотя бы одно число из массива сохранить в экспоненциальной форме.

dikiy ★★☆☆☆
()
Ответ на: комментарий от TheKnight

http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms

ниже будет Non-comparison sorts, там в графе Memory.

Я не спец во всех этих алгоритмах, но, судя по описанию, нам всегда требуется корзина(ы) размером в N которые используются на каждом проходе. Может так будет чуть более понятно: (Some LSD) radix sort implementations allocate space for buckets by first counting the number of keys that belong in each bucket before moving keys into those buckets.

Всю инфу и имплементации смотрел сдесь: http://en.wikipedia.org/wiki/Radix_sort

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

В смысле, в худшем случае нам потребуется корзина размером в N.

true_admin ★★★★★
()
Ответ на: комментарий от ebantrop

Охренеть, это круто.

Хотя я сразу подозревал, что задача сводится к поиску по графу, мозгов не хватило, чтобы найти решение. :-(

geekless ★★
()
Ответ на: комментарий от geekless

Охренеть, это круто.

Ага. Сам чуть со стула не упал, как все просто оказывается.

ebantrop
()

пусть min=0, max=n;

0)иф(min==max)return min;

1)mid=(min+max)/2

2)x=count(min <= all < mid)

3)y=count(mid <= all <= max)

4)иф(x<y) min=mid; елсе max=mid;

5)гоуто(0)

ckotinko ☆☆☆
()

Что ж, всем спасибо. Решение, которое вы нашли, является несколько необычным и заслуживающим особого внимания.

TheKnight ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.