Вот хорошее лечение. Перед решением этой проблемы он проходит через несколько простых проблем.
http://aperiodic.net/phil/archives/Geekery/find-duplicate-elements.html
Содержит решение, когда вы можете изменить входной массив, и другое, когда вы не можете.
Краткое описание на случай, если ссылка когда-либо прекратится: индексы массива начинаются с 0 .. N-1, а значения массива - 0 .. N-2. Поэтому каждый элемент массива можно рассматривать как индекс (или «указатель») в самом массиве: элемент i
«указывает на» элемент ra[i]
, ra[i]
указывает на ra[ra[i]]
и т. Д. Повторно следуя этим указателям, я должен в конечном итоге войти в цикл, потому что мы определенно не можем идти вечно, не повторно посетив тот или иной узел.
Теперь, самый последний элемент, N-1, не указан ни одним другим элементом. Поэтому, если мы начнем там и в конце концов войдем в цикл, где-то по пути должен быть элемент, к которому можно добраться из двух разных мест: маршрут, который мы выбрали в первый раз, и маршрут, который является частью цикла. Примерно так:
N-1 -> a1 -> a2 -> a3
^ \
/ v
a6 <- a5 <- a4
В этом случае a2 доступен из двух разных мест.
Но узел, который доступен из двух разных мест, это именно то, что мы ищем, дубликат в массиве (два разных элемента массива, содержащие одно и то же значение).
Тогда возникает вопрос, как определить a2, и ответом является использование Алгоритма Флойда для нахождения цикла . В частности, он сообщает нам «начало» цикла в O (N) времени и O (1) пространстве.