Существует также линейный алгоритм времени и постоянного пространства, основанный на разбиении, который может быть более гибким, если вы пытаетесь применить это к вариантам задачи, над которыми математический подход не работает должным образом. Это требует изменения базового массива и имеет худшие постоянные факторы, чем математический подход. Точнее говоря, я считаю, что затраты с точки зрения общего числа значений и количества дубликатов d равны O ( n log d ) и O ( d ) соответственно, хотя для точного подтверждения этого потребуется больше времени, чем у меня на данный момент. ,ndO(nlogd)O(d)
Алгоритм
Начните со списка пар, где первая пара - это диапазон по всему массиву, или если 1 проиндексирован.[(1,n)]
Повторяйте следующие шаги, пока список не станет пустым:
- Возьмите и удалите любую пару из списка.(i,j)
- Найти минимальное и максимальное, и максимальное обозначенного подмассива.minmax
- Если , подмассив состоит только из равных элементов. Получите его элементы, кроме одного, и пропустите шаги с 4 по 6.min=max
- Если , подмассив не содержит дубликатов. Пропустите шаги 5 и 6.max−min=j−i
- Разбить подмассив вокруг , так что элементы до некоторого индексаkменьше разделителя, а элементы выше этого индекса - нет.min+max2k
- Добавьте и ( k + 1 , j ) в список.(i,k)(k+1,j)
Беглый анализ сложности времени.
Шаги с 1 по 6 занимают время, так как поиск минимума и максимума и разбиение могут быть выполнены за линейное время.O(j−i)
Каждая пара в списке является либо первой парой ( 1 , n ) , либо дочерним элементом некоторой пары, для которой соответствующий подмассив содержит дубликат элемента. Существует не более d ⌈ log 2 n + 1 ⌉ таких родителей, так как каждый обход делит пополам диапазон, в котором может быть дубликат, таким образом, получается не более 2 d ⌈ log 2 n + 1 ⌉ всего при включении пар над подмассивами без дубликаты. Размер списка не более 2 дней(i,j)(1,n)d⌈log2n+1⌉2d⌈log2n+1⌉2d,
Рассмотрим работу по поиску любого дубликата. Он состоит из последовательности пар в экспоненциально убывающем диапазоне, поэтому общая работа представляет собой сумму геометрической последовательности или . Это дает очевидное следствие того, что общая работа для d дубликатов должна быть O ( n d ) , которая является линейной по n .O(n)dO(nd)n
Чтобы найти более жесткую границу, рассмотрим наихудший сценарий максимального распространения дубликатов. Интуитивно понятно, что поиск занимает две фазы: одна, где каждый раз просматривается полный массив, в постепенно меньших частях, и одна, где части меньше так что только части массива пройдены. Первая фаза может быть толькоглубинойlogd, поэтому имеет стоимостьO(nlogd), а вторая фаза имеет стоимостьO(n),потому что общая область поиска снова экспоненциально уменьшается.ndlogdO(nlogd)O(n)