Найти первый дублированный элемент


39

Учитывая массив 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) дополнительную сложность пространства?


Комментарии не для расширенного обсуждения; этот разговор был перемещен в чат .
Мартин Эндер

Ответы:


15

Python 2 , 34 байта

O (n 2 ) время, O (n) пространство

Благодаря @vaultah сохранено 3 байта, а еще @xnor!

lambda l:l[map(l.remove,set(l))<0]

Попробуйте онлайн!


1
Похоже, lambda l:l[map(l.remove,set(l))<0]работает, хотя порядок оценки странный.
xnor

Он не возвращается, -1если не найдены дубликаты без «кода нижнего колонтитула», не учитывается ли этот код в байтах? Я новичок в коде гольф, извините, если это основной вопрос!
Chris_Rands

@Chris_Rands Под вопросом музыкант задавал вопрос о том, в порядке ли исключение вместо -1, а OP ответил, что все в порядке, а ответ музыканта создает исключение.
LiefdeWen

Это заняло у меня некоторое время, чтобы понять. Отлично сработано. Получение 0-го элемента l с помощью условного выражения после его изменения действительно разумно.
Thoth 19

Гарантирует ли Python временную и пространственную сложность функций стандартной библиотеки, таких как set.remove?
Драконис

11

JavaScript (ES6), 47 36 31 25 байт

Сохранено 6 байтов благодаря ThePirateBay

Возвращает, undefinedесли решения не существует.

Сложность времени: O (n) :-)
Сложность пространства: O (n) :-(

a=>a.find(c=>!(a[-c]^=1))

Как?

Мы отслеживаем уже встречающиеся значения, сохраняя их как новые свойства исходного массива a , используя отрицательные числа. Таким образом, они не могут мешать оригинальным записям.

демонстрация


25 байтов:a=>a.find(c=>!(a[-c]^=1))

@ThePirateBay О, конечно. Благодарность!
Арно

Просто обратите внимание, что объекты в JavaScript не могут быть реализованы в виде хэш-таблицы. Временная сложность доступа к ключам какого-либо объекта может быть не O (1).
17

6

Mathematica, 24 байта

#/.{h=___,a_,h,a_,h}:>a&

Возможность сопоставления с образцом Mathematica - это круто!

Возвращает оригинал Listдля неверного ввода.

объяснение

#/.

На входе заменить ...

{h=___,a_,h,a_,h}

A Listс дублирующим элементом, с 0 или более элементами до, между и после дубликатов ...

... :>a

С дублирующим элементом.


6

Желе , 5 байт

Ṛœ-QṪ

Попробуйте онлайн!

Как это работает

Ṛœ-QṪ  Main link. Argument: A (array)

Ṛ      Yield A, reversed.
   Q   Unique; yield A, deduplicated.
 œ-    Perform multiset subtraction.
       This removes the rightmost occurrence of each unique element from reversed
       A, which corresponds to the leftmost occurrence in A.
    Ṫ  Take; take the rightmost remaining element, i.e., the first duplicate of A.

œ-удаляет самые правые вхождения? TIL
Эрик Outgolfer

Это, кажется, не возвращается -1без дубликатов. Бросить исключение нормально в соответствии с ОП, но я не уверен, что если, 0хотя он не находится в диапазоне.
Эрик Outgolfer


4

Желе , 6 байт

xŒQ¬$Ḣ

Попробуйте онлайн!

Возвращает первый дубликат или 0, если дубликатов нет.

объяснение

xŒQ¬$Ḣ  Input: array M
    $   Operate on M
 ŒQ       Distinct sieve - Returns a boolean mask where an index is truthy
          for the first occurrence of an element
   ¬      Logical NOT
x       Copy each value in M that many times
     Ḣ  Head

Это golfier использовать индексацию как это: ŒQi0ị.
Эрик Outgolfer

@EriktheOutgolfer Если нет дубликатов, i0вернет 0, где будет индексировать и вернуть последнее значение ввода вместо 0.
мили

4

Japt , 7 байт

æ@bX ¦Y

Проверьте это онлайн!

объяснение

 æ@   bX ¦ Y
UæXY{UbX !=Y}  Ungolfed
               Implicit: U = input array
UæXY{       }  Return the first item X (at index Y) in U where
     UbX         the first index of X in U
         !=Y     is not equal to Y.
               In other words, find the first item which has already occured.
               Implicit: output result of last expression

В качестве альтернативы:

æ@¯Y øX

Проверьте это онлайн!

объяснение

 æ@   ¯ Y øX
UæXY{Us0Y øX}  Ungolfed
               Implicit: U = input array
UæXY{       }  Return the first item X (at index Y) in U where
     Us0Y        the first Y items of U (literally U.slice(0, Y))
          øX     contains X.
               In other words, find the first item which has already occured.
               Implicit: output result of last expression

4

Pyth, 5 байт

h.-Q{

Тестирование

Удалите из Q первое появление каждого элемента в Q, затем верните первый элемент.


@ LuisMendo Хорошо, спасибо. Извините за путаницу, я должен научиться читать ...
Mr. Xcoder

@ Mr.Xcoder Нет, это вина ОП. Эта информация должна быть в тексте задачи, но только в комментарии
Луис Мендо,

4

Dyalog APL, 27 24 20 19 13 12 11 байт

⊢⊃⍨0⍳⍨⊢=⍴↑∪

Теперь модифицировано, чтобы не зависеть от v16! Попробуйте онлайн!

Как? (С вводом N )

  • ⊢⊃⍨...- N по этому показателю:
    • ⍴↑∪- N с удаленными дубликатами, с правой стороны, 0чтобы соответствовать N
    • ⊢=- Элементарное равенство с N
    • 0⍳⍨- указатель первый 0. `

неважно, я неправильно понял вопрос. не достаточно тестов, хотя ...
Уриэль

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

Похоже, 36 байтов для меня.
Адам

О, боже, йота андербар не в ⎕AV, не так ли?
Захари

@ Zacharý Право, Classic переводит его ⎕U2378 при загрузке. Попробуйте онлайн!
Адам

3

Python 3 , 94 92 байта

O (n) время и O (1) дополнительная память.

def f(a):
 r=-1
 for i in range(len(a)):t=abs(a[i])-1;r=[r,i+1][a[t]<0>r];a[t]*=-1
 return r

Попробуйте онлайн!

Источник алгоритма .

объяснение

Основная идея алгоритма состоит в том, чтобы проходить через каждый элемент слева направо, отслеживать появившиеся числа и возвращать число при достижении числа, которое уже появилось, и возвращать -1 после прохождения каждого элемента.

Однако он использует умный способ хранения появившихся чисел без использования дополнительной памяти: хранить их как знак элемента, индексированного по номеру. Например, я могу представить тот факт, что 2и 3уже появился, имея a[2]и a[3]отрицательный, если массив 1-индексирован.


Что это будет делать для iгде a [i]> n?
Вниз

@ Downgoat прочитайте вопрос еще раз.
Утренняя монахиня

Вопрос говорит 1о длине, но для длины [i] = a. это не выходит за пределы?
Вниз

@Downgoatt=abs(a[i])-1=a.length-1
Монахиня


3

Perl 6 , 13 байт

*.repeated[0]

Попытайся


объяснение

  • Он *находится в терминах Term, поэтому весь оператор - это лямбда- выражение Wh whatCode.

  • Это .repeatedметод, который приводит к каждому значению, за исключением первого раза, когда каждое значение было просмотрено.

    say [2, 3, 3, 3, 1, 5, 2, 3].repeated.perl; # (3, 3, 2, 3).Seq
    #   (      3, 3,       2, 3).Seq
  • [0]просто возвращает первое значение в Seq .
    Если значение отсутствует, возвращается ноль .
    ( Nil является основой типов Failure , и все типы имеют свое собственное неопределенное значение, поэтому Nil отличается от неопределенного значения в большинстве других языков)


Обратите внимание, что поскольку реализация.repeated генерирует Seq, это означает, что он не начинает выполнять какую-либо работу до тех пор, пока вы не запросите значение, и он только выполняет работу, достаточную для генерации того, что вы запрашиваете.
Таким образом, было бы легко утверждать, что это имеет в худшем случае O (n)  временную сложность и в лучшем случае O (2)  временную сложность, если второе значение является повторением первого.
Подобное можно, вероятно, сказать о сложности памяти.


3

APL (Dyalog) , 20 байтов

n/⍨(,≢∪)¨,\n←⎕,2⍴¯1

Попробуйте онлайн!

2⍴¯1 отрицательный г eshaped в длину-два списка

⎕, получить ввод (мнемоника: консоль) и предварять это

n← хранить это в н

,\ префиксы n (лит. кумулятивная конкатенация)

( Применить следующую молчаливую функцию к каждому префиксу

, [is] ravel (просто гарантирует, что префикс является списком)

 отличается от

 уникальные элементы [?] (т.е. есть ли у префикса дубликаты?)

n/⍨ используйте это, чтобы отфильтровать n (удаляет все элементы до тех пор, пока не будет найден первый, для которого была найдена копия)

 выбрать первый элемент из этого


Ух ты, тебя трижды избили. Тем не менее +1. И можете ли вы объяснить, как это работает?
Захари

@ Zacharý Видимо, мне просто нужно, чтобы мяч катился. Ну вот.
Адам

@ Zacharý В конце концов мне удалось победить их всех .
Адам

3

APL (Дьялог) , 11 байт

Согласно новым правилам , выдает ошибку, если дубликатов не существует.

⊢⊃⍨⍬⍴⍳∘≢~⍳⍨

Попробуйте онлайн!

⍳⍨ показатели первого появления каждого элемента

~ удалено из

⍳∘≢ из всех показателей

⍬⍴ изменить это в скаляр (дает ноль, если нет данных)

⊃⍨ использовать это, чтобы выбрать из (дает ошибку на нуле)

 Аргумент


Ну, да, когда правила меняются, конечно, вы можете победить их всех!
Захари

Ну, я связал тебя.
Захари

3

APL, 15

{⊃⍵[(⍳⍴⍵)~⍵⍳⍵]}

Похоже, мы можем вернуть 0 вместо -1, если нет дубликатов (спасибо Adám за комментарий). Так что на 3 байта меньше.

Немного описания:

⍵⍳⍵         search the argument in itself: returns for  each element the index of it's first occurrence
(⍳⍴⍵)~⍵⍳⍵   create a list of all indexes, remove those found in ⍵⍳⍵; i.e. remove all first elements
⊃⍵[...]     of all remaining elements, take the first. If the array is empty, APL returns zero

Для справки, старое решение добавило -1 к списку в конце, поэтому, если список окажется пустым, он будет содержать -1, а первый элемент будет -1.

{⊃⍵[(⍳⍴⍵)~⍵⍳⍵],¯1}

Попробуйте это на tryapl.org


Вы можете вернуть ноль вместо¯1 , так {⊃⍵[(⍳⍴⍵)~⍵⍳⍵]}должно быть.
Адам

3

Сетчатка , 26 24 байта

1!`\b(\d+)\b(?<=\b\1 .*)

Попробуйте онлайн! Объяснение: \b(\d+)\bсопоставляет каждое число по очереди, а затем просмотрщик смотрит, является ли число дубликатом; если это 1совпадение, !выводится результат, а не количество совпадений. К сожалению, размещение внешнего вида вначале не работает, иначе это сэкономит несколько байтов. Редактировать: Добавлено 7 байт для соответствия -1возвращаемому значению при отсутствии совпадения. Сохранено 2 байта благодаря @MartinEnder.


2
Для записи, взгляд не вернется. Это препятствует тому, чтобы это работало, если Вы пытаетесь поместить это прежде. Я делал эту ошибку много раз, и Мартин всегда исправляет меня.
FryAmTheEggman

Я получил 30 байтов, используя lookahead вместо lookbehind. Кроме того, правила теперь говорят, что вам не нужно возвращаться -1.
Чернила стоимости

@ValueInk Но правильный ответ для этого контрольного примера - 3 ...
Нил

ОЙ. Я неправильно понял вызов, к сожалению
Value Ink

2

MATL , 8 байт

&=Rsqf1)

Выдает ошибку (без вывода), если дубликатов не существует.

Попробуйте в MATL Online!

объяснение

&=   % Implict input. Matrix of all pairwise equality comparisons
R    % Keep the upper triangular part (i.e. set lower part to false)
s    % Sum of each column
q    % Subtract 1
f    % Indices of nonzero values
1)   % Get first. Gives an error is there is none. Implictly display

2

R, 34 байта

c((x=scan())[duplicated(x)],-1)[1]

Вырежьте несколько символов из ответа @djhurio, но у вас недостаточно репутации, чтобы комментировать.


ох ... я не видел этот ответ; это хорошо для предыдущей спецификации, когда требуются пропущенные значения, -1но с новой спецификацией мне удалось еще больше упасть. Это все еще твердо, и это отличается от того, как он это сделал, поэтому я дам вам +1!
Джузеппе

2

J, 17 16 байт

(*/{_1,~i.&0)@~:

Как?

(*/{_1,~i.&0)@~:

             @~: returns the nub sieve which is a vector with 1 for the first occurrence of an element in the argument and 0 otherwise

        i.&0     returns the first index of duplication

    _1,~         appends _1 to the index

 */              returns 0 with duplicates (product across nub sieve)

     {           select _1 if no duplicates, otherwise return the index


2

J , 12 байт

,&_1{~~:i.0:

Попробуйте онлайн!

объяснение

,&_1{~~:i.0:  Input: array M
      ~:      Nub-sieve
          0:  The constant 0
        i.    Find the index of the first occurrence of 0 (the first duplicate)
,&_1          Append -1 to M
    {~        Select the value from the previous at the index of the first duplicate

2

Dyalog APL Classic, 18 символов

Работает только в ⎕IO←0.

     w[⊃(⍳∘≢~⍳⍨)w←¯1,⎕]

Удалите из списка индексов элементов аргумента с добавленным «-1» список индексов своего куска, а затем выберите первое из того, что осталось. Если после удаления остается только пустой вектор, его первый элемент по определению 0, который используется для индексации расширенного аргумента, производящего желаемый -1.


Гм ... что со случайными ведущими пробелами? +1 за то, что превзошел меня на один байт.
Захари

Вы можете выдать ошибку вместо возврата¯1 , чтобы вы могли удалить ¯1,и использовать ⎕IO←1.
17


2

Java (OpenJDK 8) , 65 117 109 байт

Предыдущее 65-байтовое решение:

r->{for(int a,b=0,z,i=0;;b=a)if((a=b|1<<(z=r[i++]))==b)return z;}

Новое решение 19 байтов включены дляimport java.math.*;

-8 байт благодаря @Nevay

r->{int z,i=0;for(BigInteger c=BigInteger.ZERO;c.min(c=c.setBit(z=r[i++]))!=c;);return z;}

Попробуйте онлайн!

редактировать

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

Я изменил тип данных, используемый в вычислениях, чтобы увеличить лимит памяти программы, чтобы приспособиться к этому (используя 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.

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


Кроме того , ваш второй тест включает в себя номер 100, но то невозможно , так как сам массив только 5 долго
Schoolboy

Кроме того, это терпит неудачу, так как int не имеет достаточно памяти.
Schoolboy

@SchoolBoy Хороший улов. Моя единственная проблема заключается в том, что не существует какого-либо верхнего предела размера массива, поэтому я не могу реально изменить свой код для решения проблем с памятью.
Ксандерхолл

@ Xanderhall Правда, но я чувствую, что 32 (или если вы используете длинные, 64) числа слишком мало: с. В любом случае, наложение ограничения на вход, а затем выделение максимального объема памяти и вызов его O (1) памяти - просто обман. Это все равно O (n), так как, если размер входного сигнала увеличится, увеличится и эта верхняя граница для памяти. Который также , почему я считаю , что это невозможно создать O (N) O (1) алгоритм
Schoolboy

@Xanderhall PS Я получаю близко к 65, я в 67 байт: р
Schoolboy

2

PHP, 56 44 38 32 байта

for(;!${$argv[++$x]}++;);echo$x;

Запустите так:

php -nr 'for(;!${$argv[++$x]}++;);echo$x;' -- 2 3 3 1 5 2;echo
> 3

объяснение

for(
  ;
  !${                 // Loop until current value as a variable is truthy
    $argv[++$x]       // The item to check for is the next item from input
  }++;                // Post increment, the var is now truthy
);
echo $x;              // Echo the index of the duplicate.

Tweaks

  • Сохранено 12 байт с использованием переменных вместо массива
  • Сохранено 6 байтов за счет использования правила «неопределенное поведение» в случае отсутствия совпадения.
  • Сохранено 6 байтов с использованием постинкремента вместо установки в 1 после каждого цикла

сложность

Как видно из закомментированной версии кода, временная сложность линейна O(n). С точки зрения памяти, максимум n+1переменных будет назначен. Так вот O(n).


Спасибо, что не используете странную кодировку. Но вы должны добавить error_reportingопцию к числу байтов (или использовать -n, что бесплатно).
Тит

Мы были здесь раньше. Замечания и предупреждения PHP игнорируются. Я мог бы с тем же успехом передать их /dev/null, что то же самое.
aross

Я склонен помнить неправильные комментарии. :) Разве это не O (n)?
Тит

Да , это линейное
aross

Как это O(1)для дополнительного пространства? Вы буквально присваиваете новую переменную per n, а именноO(n)
Xanderhall

2

Java 8, 82 78 76 байтов Больше не жизнеспособен, 75 67 64 байтов ниже в редактировании

В качестве лямбда-функции:

a->{Set<Long>s=new HashSet<>();for(long i:a)if(!s.add(i))return i;return-1;}

Вероятно, можно сделать намного меньше, это было очень быстро.

Объяснение:

a->{                                //New lambda function with 'a' as input
    Set<Long>s=new HashSet<>();     //New set
    for(long i:a)                   //Iterate over a
        if(!s.add(i))               //If can't add to s, already exists
            return i;               //Return current value
        return-1;                   //No dupes, return -1
}

*Редактировать*

75 67 64 байта, используя стратегию отрицания:

a->{int i=0,j;while((a[j=Math.abs(a[i++])-1]*=-1)<0);return++j;}

Попробуйте онлайн!

(-3 байта благодаря @Nevay)

Объяснение:

a->{                                         //New lambda expression with 'a' as input
    int i=0,j;                               //Initialise i and declare j
    while((a[j=Math.abs(a[i++])-1]*=-1)<0);  //Negate to keep track of current val until a negative is found
    return++j;                               //Return value
}

Зацикливается на массиве, отрицая, чтобы отслеживать. Если нет дупликов, просто перебегает и выдает ошибку.

Оба они работают на O (n) времени и сложности O (n) пространства.


Стоит отметить, что это нужно будет назначить возвращению лямбды Number, так iкак есть longи -1есть int.
Якоб

@Jakob Не требуется, -1, представляющее собой ИНТ будет автоматически приводиться к долго без явного указания актерскому
Schoolboy

Он будет приводиться неявно 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 байта).
Неваи,

2

Брахилог , 5 байт

a⊇=bh

Попробуйте онлайн!

объяснение

a⊇=bh  Input is a list.
a      There is an adfix (prefix or suffix) of the input
 ⊇     and a subsequence of that adfix
  =    whose elements are all equal.
   b   Drop its first element
    h  and output the first element of the rest.

Встроенный adfix aперечисляет сначала все префиксы в порядке возрастания длины, затем суффиксы в порядке убывания длины. Таким образом, вывод производится по кратчайшему префиксу, который позволяет, если таковой имеется. Если у префикса нет дубликатов, остальная часть программы завершается с ошибкой, поскольку каждая подпоследовательность равных элементов имеет длину 1, а первый элемент его хвоста не существует. Если у префикса есть повторяющийся элемент, мы можем выбрать подпоследовательность длины-2, содержащую оба, и программа возвращает последний.


Другое 5-байтовое решение:, a⊇Ċ=hкоторое смотрит только на подмножества длины-2.
Роковая

1

C #, 145 байт

using System.Linq;a=>{var d=a.Where(n=>a.Count(t=>t==n)>1);return d.Select((n,i)=>new{n,i}).FirstOrDefault(o=>d.Take(o.i).Contains(o.n))?.n??-1;}

Вероятно, гораздо более короткий способ сделать это в C # с простым циклом, но я хотел попробовать это с Linq.

Попробуйте онлайн!

Полная / Отформатированная версия:

namespace System.Linq
{
    class P
    {
        static void Main()
        {
            Func<int[], int> f = a =>
            {
                var d = a.Where(n => a.Count(t => t == n) > 1);
                return d.Select((n, i) => new { n, i }).FirstOrDefault(o => d.Take(o.i).Contains(o.n))?.n ?? -1;
            };

            Console.WriteLine(f(new[] { 2, 3, 3, 1, 5, 2 }));
            Console.WriteLine(f(new[] { 2, 4, 3, 5, 1 }));

            Console.ReadLine();
        }
    }
}

Вот простая версия цикла. Но мне больше нравится версия Linq.
LiefdeWen

@LiefdeWen Опубликуйте это как ответ :) Хотя обычно мне также нравится Linq лучше :) Возможно, я смогу сократить его и с Linq, но теперь я уверен.
TheLethalCoder

Нет, этот вопрос перенаселен, и я бы предпочел, чтобы вы получили положительные голоса за этот вопрос.
LiefdeWen

1

Haskell , 78 69 байтов

 fst.foldl(\(i,a)(j,x)->(last$i:[j|i<0,elem x a],x:a))(-1,[]).zip[1..]

Попробуйте онлайн!

Сохранено 9 байт благодаря @nimi

Основной путь по списку. Если текущий элемент еще не был просмотрен ( i<0) и находится в списке аккумуляторов ( elem x a), сохраните текущий индекс. Остальное, держите индекс -1. В любом случае добавьте текущий элемент в список аккумуляторов.

РЕДАКТИРОВАТЬ : Я недостаточно внимательно прочитал вопрос: этот код выводит индекс второго элемента дубликата элемента.


Вы можете использовать «Шортер условный» из наших «Советов для игры в гольф в Haskell» : \ ... ->(last$i:[j|i<0,elem x a],x:a). Кроме того: нет необходимости f=, потому что разрешены безымянные функции.
Nimi

@nimi спасибо за совет!
Джерард

1

Python 2, 71 65 байт

Возвращает, Noneесли нет повторяющегося элемента

Редактировать: -6 байт благодаря @ musicman523

def f(n):
 for a in n:
	u=-abs(a)
	if n[u]<0:return-u
	n[u]=-n[u]

Попробуйте онлайн!

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 раньше.


Хорошая работа! 65 байт
musicman523

Вы уверены, что это O (1) в памяти? Вы по-прежнему используете n бит памяти для хранения номеров, которые уже были посещены, даже если эти биты находятся в знаке. Мне кажется, что это замаскированный O (n)
Wheat Wizard

Технически это использует O (n) пробел - n знаковых битов. Если массив может содержать только значения между 1и n, например, как он был задан, то он, очевидно, не работает.
Оливер Ни

Это действительно сводится к представлению, которое вы выбираете для чисел. Если используются числа без знака, то это O (n) вспомогательное пространство. Если используются числа со знаком, то знаковый бит уже существует, что означает O (1) вспомогательное пространство.
Халвард Хаммел

Я согласен с вами там. Лично я позволил бы вам скользить, используя целые числа со знаком, если вы не используете знаковый бит, это должен быть алгоритм, а не технические особенности системы. При этом я думаю, что если вы собираетесь использовать знаковые биты, вы должны их посчитать. Я думаю, что этот ответ довольно умный. Если бы я оставил какие-либо голоса сегодня, я бы проголосовал против них.
Пшеничный волшебник

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.