Tìm phần tử trùng lặp đầu tiên


39

Cho một mảng a chỉ chứa các số trong phạm vi từ 1 đến a.length, tìm số trùng lặp đầu tiên mà lần xuất hiện thứ hai có chỉ số tối thiểu. Nói cách khác, nếu có nhiều hơn 1 số trùng lặp, hãy trả về số mà lần xuất hiện thứ hai có chỉ số nhỏ hơn lần xuất hiện thứ hai của số khác. Nếu không có các yếu tố đó, chương trình / chức năng của bạn có thể dẫn đến hành vi không xác định.

Thí dụ:

Đối với a = [2, 3, 3, 1, 5, 2], đầu ra nên được firstDuplicate(a) = 3.

Có 2 bản sao: số 2 và 3. Lần xuất hiện thứ hai của 3 có chỉ số nhỏ hơn lần xuất hiện thứ hai của 2, vì vậy câu trả lời là 3.

Đối với a = [2, 4, 3, 5, 1], đầu ra nên được firstDuplicate(a) = -1.

Đây là , vì vậy câu trả lời ngắn nhất bằng byte thắng.

THƯỞNG: Bạn có thể giải quyết nó trong độ phức tạp thời gian O (n) và độ phức tạp không gian bổ sung O (1) không?


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Martin Ender

Câu trả lời:


15

Python 2 , 34 byte

Thời gian O (n 2 ), không gian O (n)

Đã lưu 3 byte nhờ @vaultah và thêm 3 byte từ @xnor!

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

Hãy thử trực tuyến!


1
Nó trông giống như lambda l:l[map(l.remove,set(l))<0]công trình, mặc dù thứ tự đánh giá là kỳ lạ.
xnor

Điều này không trả về -1khi không tìm thấy bản sao nào mà không có 'mã chân trang', mã đó có được tính vào byte không? Tôi mới chơi golf, xin lỗi nếu đó là một câu hỏi cơ bản!
Chris_Rands

@Chris_Rands Bên dưới câu hỏi nhạc sĩ đã hỏi liệu ngoại lệ có ổn không thay vì -1 và OP nói không sao và câu trả lời của nhạc sĩ ném ngoại lệ.
LiefdeWen

Điều đó làm tôi mất một lúc để tìm ra. Chơi tốt Lấy phần tử thứ 0 của l bằng cách sử dụng điều kiện sau khi sửa đổi nó thực sự rất thông minh.
Thoth19

Python có đảm bảo độ phức tạp về thời gian và không gian của các hàm thư viện chuẩn như set.remove không?
Draconis

11

JavaScript (ES6), 47 36 31 25 byte

Đã lưu 6 byte nhờ ThePirateBay

Trả về undefinednếu không có giải pháp tồn tại.

Độ phức tạp thời gian: O (n) :-)
Độ phức tạp không gian: O (n) :-(

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

Làm sao?

Chúng tôi theo dõi các giá trị đã gặp bằng cách lưu chúng dưới dạng các thuộc tính mới của mảng ban đầu a bằng cách sử dụng các số âm. Bằng cách này, họ không thể can thiệp vào các mục gốc.

Bản giới thiệu


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

@ThePirateBay Oh, tất nhiên. Cảm ơn!
Arnauld

Chỉ cần lưu ý rằng các Đối tượng trong JavaScript có thể không được triển khai dưới dạng bảng băm. Độ phức tạp thời gian của các khóa truy cập của một số đối tượng có thể không phải là O (1).
tsh

6

Toán học, 24 byte

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

Khả năng khớp mẫu của Mathicala rất tuyệt!

Trả về bản gốc Listcho đầu vào không hợp lệ.

Giải trình

#/.

Trong đầu vào, thay thế ...

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

A Listcó phần tử trùng lặp, có 0 hoặc nhiều phần tử trước, giữa và sau các phần tử trùng lặp ...

... :>a

Với yếu tố trùng lặp.


6

Thạch , 5 byte

Ṛœ-QṪ

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

Ṛœ-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.

œ-loại bỏ sự xuất hiện ngoài cùng bên phải? TIL
Erik the Outgolfer 31/07/17

Điều này dường như không trở lại -1cho không có bản sao. Ném một ngoại lệ là ổn theo OP nhưng tôi không chắc 0là có mặc dù nó không nằm trong phạm vi.
Erik the Outgolfer 31/07/17


4

Thạch , 6 byte

xŒQ¬$Ḣ

Hãy thử trực tuyến!

Trả về bản sao đầu tiên hoặc 0 nếu không có bản sao.

Giải trình

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

Đó là golfier để sử dụng lập chỉ mục như thế này : ŒQi0ị.
Erik the Outgolfer 31/07/17

@EriktheOutgolfer Nếu không có bản sao, i0sẽ trở về 0, nơi sẽ index và trả về giá trị cuối cùng của đầu vào thay vì 0.
dặm

4

Japt , 7 byte

æ@bX ¦Y

Kiểm tra nó trực tuyến!

Giải trình

 æ@   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

Cách khác:

æ@¯Y øX

Kiểm tra nó trực tuyến!

Giải trình

 æ@   ¯ 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

Bình thường, 5 byte

h.-Q{

Bộ kiểm tra

Xóa khỏi Q sự xuất hiện đầu tiên của mọi phần tử trong Q, sau đó trả về phần tử đầu tiên.


@LuisMendo Ok cảm ơn. Xin lỗi vì đã tạo ra sự nhầm lẫn, tôi nên học cách đọc ...
Ông Xcoder

@ Mr.Xcoder Không, đó là lỗi của OP. Thông tin đó nên có trong văn bản thách thức, nhưng chỉ trong một bình luận
Luis Mendo

4

Dyalog APL, 27 24 20 19 13 12 11 byte

⊢⊃⍨0⍳⍨⊢=⍴↑∪

Bây giờ sửa đổi để không phụ thuộc vào v16! Hãy thử trực tuyến!

Làm sao? (Với đầu vào N )

  • ⊢⊃⍨...- N ở chỉ số này:
    • ⍴↑∪- N với các bản sao được loại bỏ, đệm bên 0phải để phù hợp với N
    • ⊢=- Bình đẳng nguyên tố với N
    • 0⍳⍨- Chỉ số của người đầu tiên 0. `

đừng bận tâm, tôi đọc sai câu hỏi không đủ trường hợp thử nghiệm mặc dù ...
Uriel

Xin lỗi vì đã đánh lừa bạn, tôi cũng đọc sai câu hỏi.
dặm

Hình như 36 byte với tôi.
Adám

Trời ơi, iota underbar không vào ⎕AV, phải không?
Zacharý

@ Zacharý Phải, Classic dịch nó sang ⎕U2378 khi tải. Hãy thử trực tuyến!
Adám

3

Python 3 , 94 92 byte

O (n) thời gian và O (1) bộ nhớ thêm.

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

Hãy thử trực tuyến!

Nguồn của thuật toán .

Giải trình

Ý tưởng cơ bản của thuật toán là chạy qua từng phần tử từ trái sang phải, theo dõi các số đã xuất hiện và trả về số khi đạt đến một số đã xuất hiện và trả về -1 sau khi đi qua từng phần tử.

Tuy nhiên, nó sử dụng một cách thông minh để lưu trữ các số đã xuất hiện mà không cần sử dụng thêm bộ nhớ: để lưu trữ chúng dưới dạng dấu hiệu của phần tử được lập chỉ mục bởi số đó. Ví dụ, tôi có thể đại diện cho thực tế rằng 23đã xuất hiện bằng cách có a[2]a[3]phủ định, nếu mảng được lập chỉ mục 1.


Điều này sẽ làm gì ikhi một [i]> n?
Hạ cấp

@Downgoat đọc lại câu hỏi.
Nữ tu rò rỉ

Câu hỏi nói 1với a.length nhưng đối với [i] = a.length thì điều này sẽ vượt ra khỏi giới hạn?
Hạ cấp

@Downgoatt=abs(a[i])-1=a.length-1
Nữ tu bị rò rỉ


3

Perl 6 , 13 byte

*.repeated[0]

Thử nó


Giải trình

  • Các *là ở một vị trí hạn như vậy toàn bộ tuyên bố là một WhateverCode lambda.

  • Đây .repeatedlà một phương pháp dẫn đến mọi giá trị ngoại trừ lần đầu tiên mỗi giá trị được nhìn thấy.

    say [2, 3, 3, 3, 1, 5, 2, 3].repeated.perl; # (3, 3, 2, 3).Seq
    #   (      3, 3,       2, 3).Seq
  • [0]chỉ trả về giá trị đầu tiên trong Seq .
    Nếu không có giá trị Nil được trả về.
    ( Nil là cơ sở của các loại Thất bại và tất cả các loại là giá trị không xác định của riêng chúng, vì vậy Nil khác với giá trị không xác định trong hầu hết các ngôn ngữ khác)


Lưu ý rằng vì việc triển khai.repeated tạo Seq có nghĩa là nó không bắt đầu thực hiện bất kỳ công việc nào cho đến khi bạn yêu cầu một giá trị và nó chỉ thực hiện đủ công việc để tạo ra những gì bạn yêu cầu.
Vì vậy, sẽ dễ dàng tranh luận rằng điều này có  độ phức tạp thời gian O (n) tồi tệ nhất và độ phức tạp thời gian O (2) tốt nhất  nếu giá trị thứ hai là sự lặp lại của lần đầu tiên.
Tương tự có lẽ có thể nói về độ phức tạp của bộ nhớ.


3

APL (Dyalog) , 20 byte

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

Hãy thử trực tuyến!

2⍴¯1 phủ định một r được đưa vào một danh sách dài hai

⎕, nhận đầu vào (mnemonic: hộp điều khiển) và thêm vào đó

n← lưu trữ trong n

,\ tiền tố của n (ghép. tích lũy)

(...  áp dụng các chức năng ngầm sau đây để mỗi tiền tố

, [là] ravel (chỉ cần đảm bảo rằng tiền tố là một danh sách)

 khác với

 các phần tử duy nhất [?] (tức là tiền tố có trùng lặp không?)

n/⍨ sử dụng điều đó để lọc n (loại bỏ tất cả các phần tử cho đến khi phần tử đầu tiên được tìm thấy)

 chọn yếu tố đầu tiên từ đó


Wow, bạn đã đánh ba lần. Tuy nhiên, +1. Và bạn có thể thêm một lời giải thích về cách thức này hoạt động?
Zacharý

@ Zacharý Rõ ràng tôi chỉ cần bóng lăn. Bạn đi đây
Adám


3

APL (Dyalog) , 11 byte

Theo quy tắc mới , đưa ra một lỗi nếu không có bản sao tồn tại.

⊢⊃⍨⍬⍴⍳∘≢~⍳⍨

Hãy thử trực tuyến!

⍳⍨ các chỉ số xuất hiện đầu tiên của mỗi yếu tố

~ bị loại khỏi

⍳∘≢ của tất cả các chỉ số

⍬⍴ định hình lại thành vô hướng (cho 0 nếu không có dữ liệu)

⊃⍨ sử dụng để chọn từ (đưa ra lỗi về số không)

 tranh luận


Vâng, vâng, khi các quy tắc được thay đổi, tất nhiên bạn có thể đánh bại tất cả!
Zacharý

Vâng, tôi đã trói bạn.
Zacharý

3

APL, 15

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

Có vẻ như chúng ta có thể trả về 0 thay vì -1 khi không có bản sao, (cảm ơn Adám đã nhận xét). Vì vậy, 3 byte ít hơn.

Một chút mô tả:

⍵⍳⍵         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

Để tham khảo, giải pháp cũ đã thêm -1 vào danh sách ở cuối, vì vậy nếu danh sách kết thúc trống, nó sẽ chứa -1 thay vào đó và phần tử đầu tiên sẽ là -1.

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

Dùng thử trên tryapl.org


Bạn có thể trả về số 0 thay vì¯1 , vì vậy {⊃⍵[(⍳⍴⍵)~⍵⍳⍵]}nên làm.
Adám

3

Võng mạc , 26 24 byte

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

Hãy thử trực tuyến! Giải thích: \b(\d+)\blần lượt khớp từng số, và sau đó giao diện nhìn để xem liệu số đó có phải là một bản sao không; nếu đó là 1trận đấu thứ nhất là !đầu ra, chứ không phải là số lượng trận đấu. Thật không may, việc đặt giao diện trước tiên dường như không hoạt động, nếu không nó sẽ tiết kiệm được vài byte. Chỉnh sửa: Đã thêm 7 byte để tuân thủ -1giá trị trả về không khớp. Đã lưu 2 byte nhờ @MartinEnder.


2
Đối với hồ sơ, việc tìm kiếm sẽ không quay trở lại. Điều này ngăn cản điều này hoạt động nếu bạn cố gắng đặt nó trước. Tôi đã mắc lỗi này nhiều lần và Martin luôn sửa lỗi cho tôi.
FryAmTheEggman

Tôi đã nhận được 30 byte bằng cách sử dụng một cái nhìn thay vì một cái nhìn. Ngoài ra, các quy tắc bây giờ nói rằng bạn không cần phải quay lại -1.
Mực giá trị

@ValueInk Nhưng câu trả lời đúng cho trường hợp thử nghiệm đó là 3 ...
Neil

OH. Tôi đã đọc sai thử thách, rất tiếc
Value Ink

2

MATL , 8 byte

&=Rsqf1)

Đưa ra một lỗi (không có đầu ra) nếu không tồn tại trùng lặp.

Hãy thử tại MATL Online!

Giải trình

&=   % 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 byte

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

Cắt một vài ký tự khỏi câu trả lời từ @djhurio, mặc dù không có đủ danh tiếng để bình luận.


oh ... tôi đã không thấy câu trả lời này; điều này tốt cho thông số kỹ thuật trước khi thiếu các giá trị cần thiết -1nhưng với thông số kỹ thuật mới, tôi đã xoay sở để đánh bại nó nhiều hơn. Điều này vẫn vững chắc và đó là một cách tiếp cận khác với cách anh ấy đã làm, vì vậy tôi sẽ cho bạn +1!
Giuseppe

2

J, 17 16 byte

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

Làm sao?

(*/{_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

R , 28 byte

(x=scan())[duplicated(x)][1]

Hãy thử trực tuyến!


Tôi nghĩ bây giờ bạn có thể trả về NAcác giá trị bị thiếu vì thông số đã thay đổi; như vậy (x=scan())[duplicated(x)][1]là hoàn toàn hợp lệ
Giuseppe

2

J , 12 byte

,&_1{~~:i.0:

Hãy thử trực tuyến!

Giải trình

,&_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 ký tự

Chỉ hoạt động trong ⎕IO←0.

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

Xóa khỏi danh sách các chỉ số của các thành phần của đối số với "-1" được liệt kê trước các chỉ số của danh sách của nó và sau đó chọn đầu tiên của phần còn lại. Nếu sau khi loại bỏ chỉ còn một vectơ trống, phần tử đầu tiên của nó là theo định nghĩa 0 được sử dụng để lập chỉ mục cho đối số mở rộng tạo ra -1 mong muốn.


Ừm ... những gì với không gian hàng đầu ngẫu nhiên? +1 để vượt xa tôi một byte.
Zacharý

Bạn có thể ném lỗi thay vì quay lại¯1 , vì vậy bạn có thể xóa ¯1,và sử dụng ⎕IO←1.
Adám


2

Java (OpenJDK 8) , 65 117 109 byte

Giải pháp 65 byte trước đó:

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

Giải pháp mới. 19 byte được bao gồm choimport java.math.*;

-8 byte nhờ @Nevay

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

Hãy thử trực tuyến!

Chỉnh sửa

Thuật toán trong chương trình ban đầu của tôi là tốt, nhưng kích thước tĩnh của kiểu dữ liệu được sử dụng có nghĩa là nó đã phá vỡ khá nhanh khi kích thước vượt quá ngưỡng nhất định.

Tôi đã thay đổi kiểu dữ liệu được sử dụng trong tính toán để tăng giới hạn bộ nhớ của chương trình để phù hợp với điều này (sử dụng BigIntegercho độ chính xác tùy ý thay vì inthoặc long). Tuy nhiên, điều này làm cho nó tranh cãi liệu điều này có được tính là O(1)phức tạp không gian hay không.

Tôi sẽ để nguyên lời giải thích của mình bên dưới, nhưng tôi muốn nói thêm rằng bây giờ tôi tin rằng không thể đạt được O(1)sự phức tạp về không gian mà không đưa ra một số giả định.

Bằng chứng

Xác định Nlà một số nguyên sao cho 2 <= N.

Hãy Slà một danh sách đại diện cho một loạt các số nguyên ngẫu nhiên [x{1}, ..., x{N}], trong đó x{i}có các ràng buộc 1 <= x{i} <= N.

Độ phức tạp thời gian (theo ký hiệu Big-O) cần thiết để lặp qua danh sách này chính xác một lần cho mỗi phần tử là O(n)

Thách thức được đưa ra là tìm giá trị trùng lặp đầu tiên trong danh sách. Cụ thể hơn, chúng tôi đang tìm kiếm giá trị đầu tiên trong Sđó là bản sao của một mục trước đó trong danh sách.

Hãy để pqlà vị trí của hai yếu tố trong danh sách như vậy p < qx{p} == x{q}. Thử thách của chúng tôi trở thành việc tìm kiếm nhỏ nhất qthỏa mãn những điều kiện đó.

Cách tiếp cận rõ ràng cho vấn đề này là lặp qua S và kiểm tra xem chúng tôi x{i}có tồn tại trong danh sách khác không T: Nếu x{i}không tồn tại T, chúng tôi lưu trữ nó trong T. Nếu x{i}không tồn tại T, nó là giá trị trùng lặp đầu tiên và do đó nhỏ nhất q, và do đó chúng tôi trả lại nó. Hiệu quả không gian này là O(n).

Để đạt được O(1)độ phức tạp không gian trong khi duy trì O(n)độ phức tạp thời gian, chúng ta phải lưu trữ thông tin duy nhất về từng đối tượng trong danh sách trong một khoảng không gian hữu hạn. Bởi vì điều này, cách duy nhất mà bất kỳ thuật toán nào có thể thực hiện tạiO(1)độ phức tạp không gian là nếu: 1. N được đưa ra một giới hạn trên tương ứng với bộ nhớ cần thiết để lưu trữ số lượng giá trị tối đa có thể cho một kiểu dữ liệu hữu hạn cụ thể. 2. Việc gán lại một biến bất biến duy nhất không được tính vào độ phức tạp, chỉ có số lượng biến (một danh sách là nhiều biến). 3. (Dựa trên các câu trả lời khác) Danh sách này (hoặc ít nhất, các phần tử của danh sách) có thể thay đổi và kiểu dữ liệu của danh sách được đặt trước dưới dạng một số nguyên đã ký, cho phép thay đổi được thực hiện cho các phần tử trong danh sách mà không sử dụng bộ nhớ bổ sung.

Cả 1 và 3 đều yêu cầu các giả định và thông số kỹ thuật về kiểu dữ liệu, trong khi 2 yêu cầu chỉ xem xét số lượng biến để tính độ phức tạp không gian, thay vì kích thước của các biến đó. Nếu không có giả định nào được chấp nhận, sẽ không thể đạt được cả O(n)độ phức tạp thời gian và O(1)độ phức tạp không gian.

Giải trình

Whoo boy, cái này mất một thời gian dài lúng túng để nghĩ ra một chút sức mạnh não bộ.

Vì vậy, đi kiếm tiền thưởng là khó khăn. Chúng tôi cần cả hai để vận hành trên toàn bộ danh sách chính xác một lần theo dõi những giá trị nào chúng tôi đã lặp đi lặp lại mà không có độ phức tạp không gian bổ sung.

Thao tác bit giải quyết những vấn đề đó. Chúng tôi khởi tạo O(1)'lưu trữ' của chúng tôi , một cặp số nguyên, sau đó lặp qua danh sách, HOẶC nhập bit thứ i trong số nguyên đầu tiên của chúng tôi và lưu kết quả đó vào số thứ hai.

Chẳng hạn, nếu chúng ta có 1101và chúng ta thực hiện thao tác OR 10, chúng ta sẽ nhận được 1111. Nếu chúng ta làm khác HOẶC với 10, chúng ta vẫn có 1101.

Ergo, một khi chúng tôi thực hiện thao tác OR và kết thúc với cùng một số, chúng tôi đã tìm thấy bản sao của mình. Không có bản sao trong mảng khiến chương trình chạy qua và ném ngoại lệ.


Ngoài ra, bài kiểm tra thứ hai của bạn bao gồm số 100, nhưng điều đó là không thể vì bản thân mảng chỉ dài 5
SchoolBoy

Ngoài ra, điều này không thành công vì một int không có đủ dung lượng lưu trữ.
SchoolBoy

@SchoolBoy Bắt tốt. Vấn đề duy nhất của tôi là dường như không có bất kỳ giới hạn trên nào về kích thước của mảng, vì vậy tôi không thể thay đổi thực tế mã của mình để giải quyết các vấn đề về bộ nhớ.
Xanderhall

@Xanderhall Đúng, nhưng tôi cảm thấy như 32 (hoặc nếu bạn sử dụng một số dài 64) thì quá ít: p. Dù bằng cách nào, việc áp đặt giới hạn cho đầu vào, sau đó phân bổ bộ nhớ tối đa cần thiết và gọi nó là bộ nhớ O (1) chỉ là một mánh gian lận. Nó vẫn là O (n) vì nếu kích thước của đầu vào tăng lên, thì điều này sẽ giới hạn trên cho bộ nhớ. Đó cũng là lý do tại sao tôi nghĩ không thể tạo ra thuật toán O (n) O (1)
SchoolBoy

@Xanderhall PS Tôi đang tiến gần đến 65 của bạn, tôi ở mức 67 byte: p
SchoolBoy

2

PHP, 56 44 38 32 byte

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

Chạy như thế này:

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

Giải trình

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.

Tinh chỉnh

  • Đã lưu 12 byte bằng cách sử dụng các biến thay vì một mảng
  • Đã lưu 6 byte bằng cách sử dụng quy tắc "hành vi không xác định" khi không có kết quả khớp.
  • Đã lưu 6 byte bằng cách sử dụng tăng sau thay vì đặt thành 1 sau mỗi vòng lặp

Phức tạp

Như có thể thấy từ phiên bản nhận xét của mã, độ phức tạp thời gian là tuyến tính O(n). Về bộ nhớ, tối đa các n+1biến sẽ được chỉ định. Vậy đó O(n).


Cảm ơn vì đã không sử dụng một mã hóa kỳ lạ. Nhưng bạn nên thêm error_reportingtùy chọn vào số byte (hoặc sử dụng -n, miễn phí).
Tít

Chúng tôi đã ở đây trước đây. Thông báo và cảnh báo PHP là không thể biết được. Tôi cũng có thể dẫn họ đến /dev/null, đó là như nhau.
vào

Tôi có xu hướng nhớ những bình luận sai. :) Đây có phải là O (n) không?
Tít

Vâng, đó là tuyến tính
từ

Làm thế nào là O(1)cho không gian bổ sung? Bạn thực sự đang gán một biến mới cho mỗi n, đó làO(n)
Xanderhall

2

Java 8, 82 78 76 byte Không còn khả thi, 75 67 64 byte bên dưới trong chỉnh sửa

Là một hàm lambda:

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

Có lẽ có thể được làm nhỏ hơn nhiều, điều này rất nhanh chóng.

Giải trình:

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
}

*Chỉnh sửa*

75 67 64 byte sử dụng chiến lược phủ định:

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

Hãy thử trực tuyến!

(-3 byte nhờ @Nevay)

Giải trình:

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
}

Vòng lặp trên mảng, phủ định để theo dõi. Nếu không có bản sao, chỉ cần chạy qua và ném lỗi.

Cả hai đều hoạt động trên độ phức tạp không gian O (n) và O (n).


Điều đáng chú ý là điều này sẽ cần được gán cho một lambda trở lại Number, vì inó là long-1là một int.
Jakob

@Jakob Không cần thiết, -1 là số nguyên sẽ tự động được truyền dài mà không chỉ định rõ ràng dàn diễn viên
SchoolBoy

Nó sẽ truyền ngầm long, nhưng không Longtheo yêu cầu cho lambda được gán cho a Function. Bạn đã kiểm tra nó? Bất kể, giải pháp đó có thể được thay thế bằng giải pháp mới của bạn.
Jakob

Bạn có thể sử dụng các kiểu thô Set s=new HashSet();để lưu 7 byte. (Bên cạnh đó: afaik việc nhập java.util.*;phải được đưa vào số byte -> +19 byte.) Câu lệnh return có thể return++j, câu lệnh if có thể được loại bỏ a->{int i=0,j;for(;(a[j=Math.abs(a[i++])-1]*=-1)<0;);return++j;}(-3 byte).
Nevay

2

Brachylog , 5 byte

a⊇=bh

Hãy thử trực tuyến!

Giải trình

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.

Tiền tố được tích hợp sẵn aliệt kê trước tiên tất cả các tiền tố theo thứ tự tăng chiều dài, sau đó là hậu tố theo thứ tự độ dài giảm dần. Do đó, đầu ra được tạo ra bởi tiền tố ngắn nhất cho phép nó, nếu có. Nếu một tiền tố không có trùng lặp, phần còn lại của chương trình sẽ không thành công, vì mọi phần tử tiếp theo của các phần tử bằng nhau có độ dài 1 và phần tử đầu tiên của phần đuôi của nó không tồn tại. Nếu một tiền tố có một phần tử lặp lại, chúng ta có thể chọn phần tiếp theo có độ dài 2 chứa cả hai và chương trình trả về phần tử sau.


Một giải pháp 5 byte khác : a⊇Ċ=h, chỉ nhìn vào các tập con có độ dài-2.
Gây tử vong

1

C #, 145 byte

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ó lẽ cách ngắn hơn để làm điều này trong C # với một vòng lặp đơn giản nhưng tôi muốn thử nó với Linq.

Hãy thử trực tuyến!

Phiên bản đầy đủ / được định dạng:

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();
        }
    }
}

Đây là phiên bản vòng lặp đơn giản. Nhưng tôi thích phiên bản Linq hơn nhiều.
LiefdeWen

@LiefdeWen Đăng nó dưới dạng câu trả lời :) Mặc dù tôi cũng thường thích Linq hơn :) Tôi cũng có thể rút ngắn lại với Linq nhưng giờ tôi chắc chắn.
TheLethalCoder

Không, câu hỏi này quá phổ biến và tôi muốn bạn nhận được số phiếu tăng cho câu hỏi này.
LiefdeWen

1

Haskell , 78 69 byte

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

Hãy thử trực tuyến!

Đã lưu 9 byte nhờ @nimi

Một con đường cơ bản thông qua danh sách. Nếu phần tử hiện tại chưa được nhìn thấy ( i<0) và nằm trong danh sách tích lũy ( elem x a) thì lưu chỉ mục hiện tại. Khác, giữ chỉ số -1. Trong mọi trường hợp, thêm phần tử hiện tại vào danh sách tích lũy.

EDIT : Tôi đã không đọc câu hỏi đủ cẩn thận: mã này xuất ra chỉ mục của phần tử thứ hai của một phần tử trùng lặp.


Bạn có thể sử dụng "Điều kiện ngắn hơn" từ "Mẹo chơi gôn trong Haskell" của chúng tôi : \ ... ->(last$i:[j|i<0,elem x a],x:a). Ngoài ra: không cần cho f=, vì các chức năng không tên được cho phép.
nimi

@nimi cảm ơn vì tiền boa!
jferard

1

Python 2, 71 65 byte

Trả về Nonenếu không có phần tử trùng lặp

Chỉnh sửa: -6 byte nhờ @ musicman523

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

Hãy thử trực tuyến!

O (n) thời gian phức tạp, O (n) không gian phức tạp, O (1) không gian phụ trợ.

Vì danh sách đầu vào sử dụng không gian O (n) , độ phức tạp của không gian bị ràng buộc bởi điều này. Có nghĩa là chúng ta không thể có độ phức tạp không gian thấp hơn O (n)

Có sửa đổi danh sách ban đầu không, nếu điều này không được phép, chúng tôi có thể thực hiện nó trong cùng độ phức tạp với 129 byte

Giải trình

Vì mọi phần tử đều lớn hơn 0 và nhỏ hơn hoặc bằng kích thước của danh sách, nên danh sách có cho mỗi phần tử a, một phần tử trên chỉ mục a - 1 (0 được lập chỉ mục). Chúng tôi khai thác điều này bằng cách nói rằng nếu phần tử tại chỉ số i là âm, chúng tôi đã thấy nó trước đây.

Với mỗi phần tử a trong danh sách n, chúng ta để u âm giá trị tuyệt đối của a. (Chúng tôi để nó âm tính vì python có thể lập chỉ mục danh sách với các chỉ số âm và nếu không chúng tôi sẽ phải làm u=abs(a)-1 ) Nếu phần tử tại chỉ mục u trong danh sách là âm, chúng tôi đã thấy nó trước đó và do đó có thể trả về -u (để lấy giá trị tuyệt đối của a, vì tất cả các yếu tố đều dương) . Khác chúng ta đặt phần tử ở chỉ số u là âm, để nhớ rằng chúng ta đã thấy một phần tử có giá trị a trước đó.


Công việc tốt! 65 byte
musicman523

Bạn có chắc đây là O (1) trong bộ nhớ? Bạn vẫn đang sử dụng n bit bộ nhớ để lưu trữ những con số nào đã được truy cập, mặc dù các bit nằm trong dấu hiệu. Dường như với tôi rằng đây là O (n) trá hình
Wheat Wizard

Về mặt kỹ thuật, điều này sử dụng không gian O (n) - các bit dấu n. Nếu mảng chỉ có thể giữ các giá trị giữa 1n, giống như cách nó được đưa ra, thì rõ ràng nó không hoạt động.
Oliver Ni

Điều này thực sự chỉ đến với đại diện bạn chọn cho các số. Nếu số không dấu được sử dụng, thì đây là không gian phụ O (n) . Nếu số đã ký được sử dụng, thì bit dấu đã có sẵn, nghĩa là không gian phụ O (1) .
Halvard Hummel

Tôi đồng ý với bạn ở đó. Cá nhân tôi sẽ cho phép bạn trượt bằng cách sử dụng các số nguyên có chữ ký miễn là bạn không sử dụng bit dấu, đó là về thuật toán chứ không phải về kỹ thuật của hệ thống. Điều đó đang được nói tôi nghĩ rằng nếu bạn sẽ sử dụng các bit dấu bạn phải đếm chúng. Tôi nghĩ rằng câu trả lời này là khá thông minh. Nếu tôi có bất kỳ phiếu bầu nào hôm nay, tôi sẽ nâng cấp nó để chống lại downvote.
Thuật sĩ lúa mì

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.