Хорошо сбалансированное двоичное дерево. Вы найдете или вставите каждый дубликат за O (log N), где N - количество элементов в дереве, поэтому O (N log N) в целом. И вставки заказаны - вы можете определить порядок, просто изменив сравнение.
Затем вы просто читаете его, как только он закончен в глубине первого порядка и, вуаля, по убыванию значений без дубликатов.
Ваш поток 5 6 7 2 3 1 2 3
приведет к:
A> 5 B> 5 C> 6
/ / \
6 7 5
D> 6 E> 6 F> 5
/ \ / \ / \
7 5 7 3 6 2
\ / \ / / \
2 5 2 7 3 1
тогда последние 2 и 3 отбрасываются, так как они уже существуют в дереве. И когда вы обрабатываете это дерево рекурсивно (влево, ток, вправо), вы получаете 7, 6, 5, 3, 2, 1
по желанию.
Другим решением, если у вас ограниченный диапазон чисел, является логическая карта. Допустим, диапазон ввода - только цифры от 0 до 9.
Установите логический массив из 10 элементов и установите для всех значений значение false. Им, для каждого числа, установите соответствующее значение в true.
Итак, для вашего ввода (пусто ложно, t
верно):
<booleans>
0123456789
i 5| t
n 6| tt
p 7| ttt
u 2| t ttt
t 3| tt ttt
| 1| ttt ttt
| 2| ttt ttt
V 3| ttt ttt
обратная обработка логической карты выдаст 7, 6, 5, 3, 2, 1
.
Как только все числа получены, просмотрите массив в обратном порядке и выведите числа, значения которых равны true. Это O(n)
операция времени, которая может занимать больше места (это общее правило, что вы часто можете обменять пространство на время при разработке алгоритмов).
Это также будет работать для диапазонов, не начинающихся с 0 - вам просто нужно сместить все на нижнюю границу диапазона. Таким образом, если бы диапазон был от 100 до 109, у вас все равно был бы массив из 10 элементов с индексом i
, представляющим число i + 100
.
Однако, если диапазон большой и числа редкие, я бы придерживался древовидной структуры.