Учитывая массив a, который содержит только числа в диапазоне от 1 до a.length, найдите первый дубликат числа, для которого второе вхождение имеет минимальный индекс. Другими словами, если имеется более 1 дублированного числа, вернуть номер, для которого второе вхождение имеет меньший индекс, чем второе вхождение другого числа. Если таких элементов нет, ваша программа / функция может привести к неопределенному поведению.
Пример:
Для a = [2, 3, 3, 1, 5, 2]
, выход должен быть
firstDuplicate(a) = 3
.
Есть 2 дубликата: номера 2 и 3. Второе вхождение 3 имеет меньший индекс, чем второе вхождение 2, поэтому ответ 3.
Для a = [2, 4, 3, 5, 1]
, выход должен быть
firstDuplicate(a) = -1
.
Это код-гольф , поэтому выигрывает самый короткий ответ в байтах.
БОНУС: Можете ли вы решить это за O (n) сложность времени и O (1) дополнительную сложность пространства?
источник
Ответы:
Python 2 , 34 байта
O (n 2 ) время, O (n) пространство
Благодаря @vaultah сохранено 3 байта, а еще @xnor!
Попробуйте онлайн!
источник
lambda l:l[map(l.remove,set(l))<0]
работает, хотя порядок оценки странный.-1
если не найдены дубликаты без «кода нижнего колонтитула», не учитывается ли этот код в байтах? Я новичок в коде гольф, извините, если это основной вопрос!JavaScript (ES6),
47363125 байтСохранено 6 байтов благодаря ThePirateBay
Возвращает,
undefined
если решения не существует.Сложность времени: O (n) :-)
Сложность пространства: O (n) :-(
Как?
Мы отслеживаем уже встречающиеся значения, сохраняя их как новые свойства исходного массива a , используя отрицательные числа. Таким образом, они не могут мешать оригинальным записям.
демонстрация
Показать фрагмент кода
источник
a=>a.find(c=>!(a[-c]^=1))
Mathematica, 24 байта
Возможность сопоставления с образцом Mathematica - это круто!
Возвращает оригинал
List
для неверного ввода.объяснение
На входе заменить ...
A
List
с дублирующим элементом, с 0 или более элементами до, между и после дубликатов ...С дублирующим элементом.
источник
Желе , 5 байт
Попробуйте онлайн!
Как это работает
источник
œ-
удаляет самые правые вхождения? TIL-1
без дубликатов. Бросить исключение нормально в соответствии с ОП, но я не уверен, что если,0
хотя он не находится в диапазоне.Haskell , 35 байт
Попробуйте онлайн! Сбои, если дубликат не найден.
источник
Желе , 6 байт
Попробуйте онлайн!
Возвращает первый дубликат или 0, если дубликатов нет.
объяснение
источник
ŒQi0ị
.i0
вернет 0, гдеị
будет индексировать и вернуть последнее значение ввода вместо 0.Japt , 7 байт
Проверьте это онлайн!
объяснение
В качестве альтернативы:
Проверьте это онлайн!
объяснение
источник
Pyth, 5 байт
Тестирование
Удалите из Q первое появление каждого элемента в Q, затем верните первый элемент.
источник
Dyalog APL,
27242019131211 байтТеперь модифицировано, чтобы не зависеть от v16! Попробуйте онлайн!
Как? (С вводом N )
⊢⊃⍨...
- N по этому показателю:⍴↑∪
- N с удаленными дубликатами, с правой стороны,0
чтобы соответствовать N⊢=
- Элементарное равенство с N0⍳⍨
- указатель первый0
. `источник
⎕AV
, не так ли?⎕U2378
при загрузке. Попробуйте онлайн!Python 3 ,
9492 байтаO (n) время и O (1) дополнительная память.
Попробуйте онлайн!
Источник алгоритма .
объяснение
Основная идея алгоритма состоит в том, чтобы проходить через каждый элемент слева направо, отслеживать появившиеся числа и возвращать число при достижении числа, которое уже появилось, и возвращать -1 после прохождения каждого элемента.
Однако он использует умный способ хранения появившихся чисел без использования дополнительной памяти: хранить их как знак элемента, индексированного по номеру. Например, я могу представить тот факт, что
2
и3
уже появился, имеяa[2]
иa[3]
отрицательный, если массив 1-индексирован.источник
i
где a [i]> n?1
о длине, но для длины [i] = a. это не выходит за пределы?t=abs(a[i])-1=a.length-1
Perl 6 , 13 байт
Попытайся
объяснение
Он
*
находится в терминах Term, поэтому весь оператор - это лямбда- выражение Wh whatCode.Это
.repeated
метод, который приводит к каждому значению, за исключением первого раза, когда каждое значение было просмотрено.[0]
просто возвращает первое значение в Seq .Если значение отсутствует, возвращается ноль .
( Nil является основой типов Failure , и все типы имеют свое собственное неопределенное значение, поэтому Nil отличается от неопределенного значения в большинстве других языков)
Обратите внимание, что поскольку реализация
.repeated
генерирует Seq, это означает, что он не начинает выполнять какую-либо работу до тех пор, пока вы не запросите значение, и он только выполняет работу, достаточную для генерации того, что вы запрашиваете.Таким образом, было бы легко утверждать, что это имеет в худшем случае O (n) временную сложность и в лучшем случае O (2) временную сложность, если второе значение является повторением первого.
Подобное можно, вероятно, сказать о сложности памяти.
источник
APL (Dyalog) , 20 байтов
Попробуйте онлайн!
2⍴¯1
отрицательный г eshaped в длину-два списка⎕,
получить ввод (мнемоника: консоль) и предварять этоn←
хранить это в н,\
префиксы n (лит. кумулятивная конкатенация)(
…)¨
Применить следующую молчаливую функцию к каждому префиксу,
[is] ravel (просто гарантирует, что префикс является списком)≢
отличается от∪
уникальные элементы [?] (т.е. есть ли у префикса дубликаты?)n/⍨
используйте это, чтобы отфильтровать n (удаляет все элементы до тех пор, пока не будет найден первый, для которого была найдена копия)⊃
выбрать первый элемент из этогоисточник
APL (Дьялог) , 11 байт
Согласно новым правилам , выдает ошибку, если дубликатов не существует.
Попробуйте онлайн!
⍳⍨
показатели первого появления каждого элемента~
удалено из⍳∘≢
из всех показателей⍬⍴
изменить это в скаляр (дает ноль, если нет данных)⊃⍨
использовать это, чтобы выбрать из (дает ошибку на нуле)⊢
Аргументисточник
APL, 15
Похоже, мы можем вернуть 0 вместо -1, если нет дубликатов (спасибо Adám за комментарий). Так что на 3 байта меньше.
Немного описания:
Для справки, старое решение добавило -1 к списку в конце, поэтому, если список окажется пустым, он будет содержать -1, а первый элемент будет -1.
Попробуйте это на tryapl.org
источник
¯1
, так{⊃⍵[(⍳⍴⍵)~⍵⍳⍵]}
должно быть.Сетчатка ,
2624 байтаПопробуйте онлайн! Объяснение:
\b(\d+)\b
сопоставляет каждое число по очереди, а затем просмотрщик смотрит, является ли число дубликатом; если это1
совпадение,!
выводится результат, а не количество совпадений. К сожалению, размещение внешнего вида вначале не работает, иначе это сэкономит несколько байтов. Редактировать:Добавлено 7 байт для соответствияСохранено 2 байта благодаря @MartinEnder.-1
возвращаемому значению при отсутствии совпадения.источник
-1
.MATL , 8 байт
Выдает ошибку (без вывода), если дубликатов не существует.
Попробуйте в MATL Online!
объяснение
источник
R, 34 байта
Вырежьте несколько символов из ответа @djhurio, но у вас недостаточно репутации, чтобы комментировать.
источник
-1
но с новой спецификацией мне удалось еще больше упасть. Это все еще твердо, и это отличается от того, как он это сделал, поэтому я дам вам +1!J,
1716 байтКак?
источник
R , 28 байт
Попробуйте онлайн!
источник
NA
пропущенные значения, так как спецификация изменилась; так(x=scan())[duplicated(x)][1]
совершенно верно.J , 12 байт
Попробуйте онлайн!
объяснение
источник
Dyalog APL Classic, 18 символов
Работает только в
⎕IO←0
.Удалите из списка индексов элементов аргумента с добавленным «-1» список индексов своего куска, а затем выберите первое из того, что осталось. Если после удаления остается только пустой вектор, его первый элемент по определению 0, который используется для индексации расширенного аргумента, производящего желаемый -1.
источник
¯1
, чтобы вы могли удалить¯1,
и использовать⎕IO←1
.Рубин ,
2836 байтВ первый раз неправильно понял вызов.
O(n)
время,O(n)
пространство.Попробуйте онлайн!
источник
Java (OpenJDK 8) ,
65117109 байтПредыдущее 65-байтовое решение:
Новое решение 19 байтов включены для
import java.math.*;
-8 байт благодаря @Nevay
Попробуйте онлайн!
редактировать
Алгоритм в моей исходной программе был в порядке, но статический размер используемого типа данных означал, что он сломался довольно быстро, как только размер превысил определенный порог.
Я изменил тип данных, используемый в вычислениях, чтобы увеличить лимит памяти программы, чтобы приспособиться к этому (используя
BigInteger
для произвольной точности вместоint
илиlong
). Однако, это делает спорным, считается ли этоO(1)
сложностью пространства.Я оставлю свое объяснение ниже без изменений, но я хочу добавить, что теперь я считаю, что невозможно достичь
O(1)
космической сложности без некоторых предположений.доказательство
Определите
N
как целое число такое, что2 <= N
.Позвольте
S
быть список, представляющий ряд случайных целых чисел[x{1}, ..., x{N}]
, гдеx{i}
имеет ограничение1 <= x{i} <= N
.Сложность по времени (в обозначениях Big-O), необходимая для итерации по этому списку ровно один раз для каждого элемента, равна
O(n)
Задача состоит в том, чтобы найти первое дублированное значение в списке. Более конкретно, мы ищем первое значение,
S
которое является дубликатом предыдущего элемента в списке.Позвольте
p
иq
быть позиции двух элементов в списке, чтоp < q
иx{p} == x{q}
. Наша задача - найти самое маленькоеq
, удовлетворяющее этим условиям.Очевидный подход к этой проблеме - перебрать S и проверить,
x{i}
существует ли наш объект в другом спискеT
: еслиx{i}
его нет вT
, мы сохраняем его вT
. Еслиx{i}
существует вT
, это первое дублирующее значение и, следовательно, наименьшееq
, и как таковое мы возвращаем его. Эта космическая эффективность естьO(n)
.Чтобы достичь
O(1)
пространственной сложности при сохраненииO(n)
временной сложности, мы должны хранить уникальную информацию о каждом объекте в списке в ограниченном количестве пространства. Из-за этого единственный способ, которым любой алгоритм мог работать вO(1)
Сложность пространства заключается в том, что: 1. N задана верхняя граница, соответствующая памяти, необходимой для хранения максимального количества возможных значений для конкретного конечного типа данных. 2. Переназначение одной неизменяемой переменной не учитывается в зависимости от сложности, а только от количества переменных (список состоит из нескольких переменных). 3. (Основано на других ответах) Список (или, по крайней мере, элементы списка) изменчив, а тип данных списка предварительно задан как целое число со знаком, что позволяет вносить изменения в элементы, находящиеся далее в списке. без использования дополнительной памяти.1 и 3 требуют предположений и спецификаций о типе данных, в то время как 2 требует, чтобы при расчете сложности пространства учитывалось только количество переменных, а не их размер. Если ни одно из этих допущений не будет принято, было бы невозможно достичь как
O(n)
временной, так иO(1)
пространственной сложности.объяснение
Черт возьми, этот занял
смущающе много времени, чтобы придуматьнемного умственных способностей.Итак, идти за бонусом сложно. Нам нужно одновременно работать со всем списком ровно один раз и отслеживать, какие значения мы уже перебрали, без дополнительной сложности с пространством.
Битовая манипуляция решает эти проблемы. Мы инициализируем наше
O(1)
«хранилище», пару целых чисел, затем выполняем итерацию по списку, ИЛИ вставляем i-й бит в наше первое целое число и сохраняем этот результат во втором.Например, если у нас есть
1101
, и мы выполняем операцию ИЛИ10
, мы получаем1111
. Если мы сделаем еще одно ИЛИ с нами10
, у нас все еще будет1101
.Поэтому, как только мы выполним операцию ИЛИ и получим тот же номер, мы нашли наш дубликат. Отсутствие дубликатов в массиве приводит к тому, что программа запускается и выдает исключение.
источник
PHP,
56 44 3832 байтаЗапустите так:
объяснение
Tweaks
сложность
Как видно из закомментированной версии кода, временная сложность линейна
O(n)
. С точки зрения памяти, максимумn+1
переменных будет назначен. Так вотO(n)
.источник
error_reporting
опцию к числу байтов (или использовать-n
, что бесплатно)./dev/null
, что то же самое.O(1)
для дополнительного пространства? Вы буквально присваиваете новую переменную pern
, а именноO(n)
Java 8,
827876 байтовБольше не жизнеспособен,756764 байтов ниже в редактированииВ качестве лямбда-функции:
Вероятно, можно сделать намного меньше, это было очень быстро.
Объяснение:
*Редактировать*
756764 байта, используя стратегию отрицания:Попробуйте онлайн!
(-3 байта благодаря @Nevay)
Объяснение:
Зацикливается на массиве, отрицая, чтобы отслеживать. Если нет дупликов, просто перебегает и выдает ошибку.
Оба они работают на O (n) времени и сложности O (n) пространства.
источник
Number
, такi
как естьlong
и-1
естьint
.long
, но не так,Long
как требуется для лямбды, которая будет назначена дляFunction
. Вы проверяли это? В любом случае, это решение может быть заменено вашим новым.Set s=new HashSet();
для сохранения 7 байтов. (Кроме того: afaik импортjava.util.*;
должен быть включен в число байтов -> +19 байт.) Оператор return может бытьreturn++j
, оператор if может быть удаленa->{int i=0,j;for(;(a[j=Math.abs(a[i++])-1]*=-1)<0;);return++j;}
(-3 байта).Брахилог , 5 байт
Попробуйте онлайн!
объяснение
Встроенный adfix
a
перечисляет сначала все префиксы в порядке возрастания длины, затем суффиксы в порядке убывания длины. Таким образом, вывод производится по кратчайшему префиксу, который позволяет, если таковой имеется. Если у префикса нет дубликатов, остальная часть программы завершается с ошибкой, поскольку каждая подпоследовательность равных элементов имеет длину 1, а первый элемент его хвоста не существует. Если у префикса есть повторяющийся элемент, мы можем выбрать подпоследовательность длины-2, содержащую оба, и программа возвращает последний.источник
a⊇Ċ=h
которое смотрит только на подмножества длины-2.C #, 145 байт
Вероятно, гораздо более короткий способ сделать это в C # с простым циклом, но я хотел попробовать это с Linq.
Попробуйте онлайн!
Полная / Отформатированная версия:
источник
Haskell ,
7869 байтовПопробуйте онлайн!
Сохранено 9 байт благодаря @nimi
Основной путь по списку. Если текущий элемент еще не был просмотрен (
i<0
) и находится в списке аккумуляторов (elem x a
), сохраните текущий индекс. Остальное, держите индекс -1. В любом случае добавьте текущий элемент в список аккумуляторов.РЕДАКТИРОВАТЬ : Я недостаточно внимательно прочитал вопрос: этот код выводит индекс второго элемента дубликата элемента.
источник
\ ... ->(last$i:[j|i<0,elem x a],x:a)
. Кроме того: нет необходимостиf=
, потому что разрешены безымянные функции.Python 2,
7165 байтВозвращает,
None
если нет повторяющегося элементаРедактировать: -6 байт благодаря @ musicman523
Попробуйте онлайн!
O (n) временная сложность, O (n) пространственная сложность, O (1) вспомогательное пространство.
Поскольку входной список использует пространство O (n) , сложность пространства связана с этим. Это означает, что мы не можем иметь меньшую сложность пространства, чем O (n)
Изменяет ли исходный список, если это не разрешено, мы можем сделать это в той же сложности с 129 байтами
объяснение
Поскольку каждый элемент больше 0 и меньше или равен размеру списка, список имеет для каждого элемента a элемент с индексом a - 1 (индексированный 0). Мы используем это, говоря, что если элемент с индексом i отрицателен, мы видели это раньше.
Для каждого элемента a в списке n мы допустим, чтобы u было отрицательным по абсолютному значению a. (Мы допускаем, чтобы он был отрицательным, поскольку python может индексировать списки с отрицательными индексами, и в противном случае мы должны были бы это сделать
u=abs(a)-1
). Если элемент с индексом u в списке является отрицательным, мы видели это раньше и поэтому можем вернуть -u (чтобы получить абсолютное значение, так как все элементы являются положительными) . В противном случае мы устанавливаем элемент с индексом u как отрицательный, чтобы помнить, что мы видели элемент со значением a раньше.источник
1
иn
, например, как он был задан, то он, очевидно, не работает.Желе , 4 байта
Попробуйте онлайн!
В случае, если все элементы уникальны, возвращается
0
(неопределенное поведение).источник