ค้นหาองค์ประกอบที่ซ้ำกันครั้งแรก


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) ความซับซ้อนของพื้นที่เพิ่มเติมหรือไม่


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Martin Ender

คำตอบ:


15

Python 2 , 34 ไบต์

เวลา O (n 2 ), พื้นที่ O (n)

บันทึก 3 ไบต์ขอบคุณ @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 โดยใช้เงื่อนไขหลังจากแก้ไขแล้วมันฉลาดจริงๆ
Th1919

Python รับประกันความซับซ้อนของเวลาและพื้นที่ของฟังก์ชั่นไลบรารีมาตรฐานเช่น set.remove หรือไม่
Draconis

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 โอ้แน่นอน ขอบคุณ!
Arnauld

เพียงสังเกตว่าวัตถุใน JavaScript อาจไม่สามารถใช้งานเป็นตารางแฮชได้ ความซับซ้อนของเวลาในการเข้าถึงคีย์ของวัตถุบางอย่างอาจไม่ใช่ O (1)
tsh

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
Erik the Outgolfer

ดูเหมือนว่าจะไม่ส่งคืน-1เนื่องจากไม่มีรายการซ้ำ การโยนข้อยกเว้นก็โอเคตาม OP แต่ฉันไม่แน่ใจว่า0ถึงแม้ว่ามันจะไม่อยู่ในช่วง
Erik the 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ịกับการใช้การจัดทำดัชนีเช่นนี้
Erik the Outgolfer

@EriktheOutgolfer หากไม่มีการซ้ำซ้อนi0จะส่งคืน 0 ซึ่งจะจัดทำดัชนีและคืนค่าสุดท้ายของอินพุตแทน 0.
ไมล์

4

Japtap , 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 ตกลงขอบคุณ ขออภัยในการสร้างความสับสนฉันควรเรียนรู้ที่จะอ่าน ...
นาย Xcoder

@ Mr.Xcoder ไม่มันเป็นความผิดของ OP ข้อมูลนั้นควรอยู่ในข้อความท้าทาย แต่มีเพียงความคิดเห็น
หลุยส์เมนโด

4

Dyalog APL, 27 24 20 19 13 12 11 ไบต์

⊢⊃⍨0⍳⍨⊢=⍴↑∪

ตอนนี้แก้ไขเพื่อไม่ขึ้นอยู่กับ v16! ลองออนไลน์!

อย่างไร? (ด้วยอินพุตN )

  • ⊢⊃⍨...- Nที่ดัชนีนี้:
    • ⍴↑∪- Nมีการลบรายการที่ซ้ำกัน, บุด้านขวาด้วย0เพื่อให้พอดีกับN
    • ⊢=- ความเท่าเทียมกันขององค์ประกอบที่ชาญฉลาดด้วยN
    • 0⍳⍨- 0ดัชนีแรก `

ไม่เป็นไรฉันอ่านคำถามผิด กรณีทดสอบไม่เพียงพอ ...
Uriel

ขออภัยที่ทำให้คุณเข้าใจผิดฉันยังอ่านคำถามผิด
ไมล์

ดูเหมือนว่า 36 ไบต์กับฉัน
Adám

โอ้พระเจ้า iota underbar ไม่ได้⎕AVอยู่ใช่ไหม?
Zacharý

@ Zacharýใช่คลาสสิกแปลเป็น⎕U2378 เมื่อโหลด ลองออนไลน์!
Adám

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[i]> n
Downgoat

@ Downgoat อ่านคำถามอีกครั้ง
Leun Nun

คำถามบอก1กับ a.length แต่สำหรับ [i] = a.length จะไม่เกินขอบเขตหรือ
Downgoat

@Downgoatt=abs(a[i])-1=a.length-1
Nun


3

Perl 6 , 13 ไบต์

*.repeated[0]

ลองมัน


คำอธิบาย

  • *อยู่ในตำแหน่งที่มีระยะเวลาเพื่อให้คำสั่งทั้งหมดเป็นWhateverCodeแลมบ์ดา

  • นี่.repeatedเป็นวิธีการที่ให้ผลลัพธ์ทุกค่ายกเว้นครั้งแรกที่เห็นแต่ละค่า

    say [2, 3, 3, 3, 1, 5, 2, 3].repeated.perl; # (3, 3, 2, 3).Seq
    #   (      3, 3,       2, 3).Seq
  • [0]เพียงแค่ส่งกลับค่าแรกในลำดับ
    หากไม่มีค่าNilจะถูกส่งกลับ
    ( ไม่มีเป็นฐานของประเภทความล้มเหลวและทุกประเภทเป็นค่าที่ไม่ได้กำหนดดังนั้นจึงไม่มีความแตกต่างจากค่าที่ไม่ได้กำหนดในภาษาอื่น ๆ ส่วนใหญ่)


หมายเหตุว่าตั้งแต่การดำเนินการ.repeatedสร้างลำดับนั่นหมายความว่ามันไม่ได้เริ่มต้นการทำงานใด ๆ จนกว่าคุณขอค่าและมันเพียง แต่การทำงานมากพอที่จะสร้างสิ่งที่คุณขอ
ดังนั้นจึงเป็นการง่ายที่จะโต้แย้งว่าสิ่งนี้มี ความซับซ้อนของเวลาO (n)ที่เลวร้ายที่สุดและที่ซับซ้อนที่สุดของเวลาO (2)  ถ้าค่าที่สองเป็นการทำซ้ำของครั้งแรก
ที่คล้ายกันอาจจะพูดถึงความซับซ้อนของหน่วยความจำ


3

APL (Dyalog) 20 ไบต์

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

ลองออนไลน์!

2⍴¯1 ลบหนึ่งrแชร์ลงในรายการความยาวสองรายการ

⎕, รับอินพุต (ช่วยในการจำ: กล่องคอนโซล) และเติมเข้าไปที่

n← เก็บที่ในn

,\ คำนำหน้าของn (lit. การต่อข้อมูลแบบรวมสะสม)

(...  ใช้ฟังก์ชัน tacit ต่อไปนี้กับแต่ละส่วนนำหน้า

, [คือ] ravel (เพียงตรวจสอบให้แน่ใจว่าคำนำหน้าเป็นรายการ)

 แตกต่างจาก

 องค์ประกอบที่ไม่ซ้ำกัน [?] (เช่นคำนำหน้ามีซ้ำกัน?)

n/⍨ ใช้สิ่งนั้นเพื่อกรองn (ลบองค์ประกอบทั้งหมดจนกว่าอันแรกที่พบสำเนาซ้ำ)

 เลือกองค์ประกอบแรกจากนั้น


ว้าวคุณชนะได้สามครั้งแล้ว ถึงกระนั้น +1 และคุณสามารถเพิ่มคำอธิบายเกี่ยวกับวิธีการทำงานของมันได้หรือไม่?
Zacharý

@ Zacharýเห็นได้ชัดว่าฉันแค่ต้องการที่จะได้รับลูกบอลกลิ้ง ไปเลย
อดัม


3

APL (Dyalog) 11 ไบต์

ตามกฎใหม่โยนข้อผิดพลาดหากไม่มีการซ้ำกันอยู่

⊢⊃⍨⍬⍴⍳∘≢~⍳⍨

ลองออนไลน์!

⍳⍨ ดัชนีของการเกิดขึ้นครั้งแรกของแต่ละองค์ประกอบ

~ นำออกจาก

⍳∘≢ ของดัชนีทั้งหมด

⍬⍴ เปลี่ยนรูปร่างที่เป็นสเกลาร์ (ให้เป็นศูนย์หากไม่มีข้อมูล)

⊃⍨ ใช้ที่จะเลือกจาก (ให้ข้อผิดพลาดในศูนย์)

 อาร์กิวเมนต์


ใช่เมื่อกฎมีการเปลี่ยนแปลงแน่นอนคุณสามารถเอาชนะพวกเขาทั้งหมด!
Zacharý

ฉันผูกคุณไว้
Zacharý

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 26ไบต์

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

ลองออนไลน์! คำอธิบาย: \b(\d+)\bจับคู่แต่ละหมายเลขตามลำดับจากนั้น lookbehind จะดูว่าหมายเลขนั้นซ้ำกันหรือไม่ ถ้ามันคือการ1แข่งขันเซนต์คือ!เอาท์พุทมากกว่าการนับการแข่งขัน น่าเสียดายที่การวาง lookbehind ก่อนดูเหมือนจะไม่ทำงานไม่เช่นนั้นจะประหยัดหลายไบต์ แก้ไข: เพิ่ม 7 ไบต์เพื่อให้สอดคล้องกับ-1ค่าส่งคืนเมื่อไม่มีการจับคู่ บันทึก 2 ไบต์ด้วย @MartinEnder


2
สำหรับบันทึกการค้นหาจะไม่ย้อนกลับ สิ่งนี้จะป้องกันไม่ให้ทำงานหากคุณพยายามใส่ไว้ก่อน ฉันทำผิดพลาดหลายครั้งและมาร์ตินแก้ไขฉันเสมอ
FryAmTheEggman

ฉันได้ 30 ไบต์โดยใช้ lookahead แทนที่จะเป็น lookbehind -1นอกจากนี้กฎระเบียบตอนนี้บอกว่าคุณไม่จำเป็นที่จะต้องกลับมา
หมึกมูลค่า

@ValueInk แต่คำตอบที่ถูกต้องสำหรับกรณีทดสอบนั้นคือ 3 ...
Neil

OH ฉันเข้าใจผิดความท้าทายอ๊ะ
หมึกมูลค่า

2

MATL , 8 ไบต์

&=Rsqf1)

ให้ข้อผิดพลาด (ไม่มีเอาต์พุต) หากไม่มีการทำซ้ำ

ลองที่MATL ออนไลน์!

คำอธิบาย

&=   % 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 แก่คุณ!
Giuseppe

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

R , 28 ไบต์

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

ลองออนไลน์!


ฉันคิดว่าตอนนี้คุณสามารถคืนNAค่าที่หายไปได้เนื่องจาก spec มีการเปลี่ยนแปลง ดังนั้น(x=scan())[duplicated(x)][1]ถูกต้องสมบูรณ์
Giuseppe


2

Dyalog APL Classic, 18 ตัวอักษร

⎕IO←0จะทำงานเฉพาะใน

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

ลบออกจากรายการดัชนีขององค์ประกอบของการโต้แย้งด้วยการเติม "-1" ดัชนีรายการของ nub ของมันแล้วเลือกแรกของสิ่งที่เหลือ หากหลังจากการลบยังคงมีเพียงเวกเตอร์ที่ว่างเปล่าองค์ประกอบแรกของมันคือโดยนิยาม 0 ซึ่งใช้ในการจัดทำดัชนีข้อโต้แย้งขยายการผลิตที่ต้องการ -1


อืม ... ช่องว่างนำหน้าแบบสุ่มคืออะไร +1 เมื่อเทียบกับฉันทีละหนึ่งไบต์
Zacharý

คุณอาจจะโยนความผิดพลาดแทนที่จะกลับ¯1เพื่อให้คุณสามารถลบและการใช้งาน¯1, ⎕IO←1
Adám


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)ความซับซ้อนของพื้นที่โดยไม่ต้องตั้งสมมติฐาน

พิสูจน์

กำหนดเป็นจำนวนเต็มเช่นว่าN2 <= 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)'พื้นที่เก็บข้อมูล' ของเราเป็นจำนวนเต็มคู่จากนั้นวนซ้ำตามรายการหรือเติมบิต ith ในจำนวนเต็มแรกของเราและเก็บผลลัพธ์นั้นเป็นวินาที

ตัวอย่างเช่นถ้าเรามี1101และเราดำเนินการหรือการดำเนินการกับเราได้รับ10 1111ถ้าเราทำอีกหรือเรายังมี101101

ดังนั้นเมื่อเราดำเนินการ OR และสิ้นสุดด้วยหมายเลขเดียวกันเราพบสำเนาของเราแล้ว ไม่มีการทำซ้ำในอาเรย์ทำให้โปรแกรมรันและโยนข้อยกเว้น


นอกจากนี้การทดสอบครั้งที่สองของคุณรวมถึงหมายเลข 100 แต่นั่นเป็นไปไม่ได้เนื่องจากอาร์เรย์มีเพียง 5 ตัวเท่านั้น
SchoolBoy

นอกจากนี้สิ่งนี้ล้มเหลวเนื่องจาก int มีพื้นที่เก็บข้อมูลไม่เพียงพอ
SchoolBoy

@ SchoolBoy จับได้ดี ปัญหาเดียวของฉันคือดูเหมือนว่าจะไม่มีข้อ จำกัด ด้านบนของขนาดของอาร์เรย์ดังนั้นฉันจึงไม่สามารถเปลี่ยนรหัสของฉันเพื่อแก้ไขปัญหาหน่วยความจำแบบสมจริง
Xanderhall

@Xanderhall จริง แต่ฉันรู้สึกว่าตัวเลข 32 (หรือถ้าคุณใช้ตัวเลขที่ยาว 64) น้อยเกินไป: p ทั้งสองวิธีกำหนดขีด จำกัด อินพุตและจัดสรรหน่วยความจำสูงสุดที่จำเป็นและเรียกมันว่าหน่วยความจำ O (1) เป็นเพียงการโกง มันยังคงเป็น O (n) ตั้งแต่ถ้าขนาดของอินพุตเพิ่มขึ้นดังนั้นขอบเขตบนของหน่วยความจำนี้ ซึ่งเป็นสาเหตุที่ฉันคิดว่ามันเป็นไปไม่ได้ที่จะสร้างอัลกอริทึม O (n) O (1)
SchoolBoy

@Xanderhall PS ฉันได้รับใกล้กับ 65 ของคุณฉันอยู่ที่ 67 ไบต์: p
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.

การปรับแต่ง

  • บันทึก 12 ไบต์โดยใช้ตัวแปรแทนที่จะเป็นอาร์เรย์
  • บันทึก 6 ไบต์โดยใช้กฎ "พฤติกรรมที่ไม่ได้กำหนด" สำหรับเมื่อไม่มีการจับคู่
  • บันทึก 6 ไบต์โดยใช้การเพิ่มภายหลังแทนที่จะตั้งค่าเป็น 1 หลังจากการวนซ้ำแต่ละครั้ง

ความซับซ้อน

O(n)ที่สามารถเห็นได้จากรุ่นความเห็นของรหัสที่ซับซ้อนเวลาเป็นเส้นตรง ในแง่ของหน่วยความจำn+1ตัวแปรสูงสุดจะถูกกำหนด O(n)ดังนั้นที่


ขอบคุณที่ไม่ใช้การเข้ารหัสแปลก ๆ แต่คุณควรเพิ่มerror_reportingตัวเลือกในการนับไบต์ (หรือใช้-nซึ่งฟรี)
ติตัส

เราเคยมาที่นี่มาก่อน คำเตือนและคำเตือนของ PHP นั้นไม่อาจเพิกเฉยได้ ฉันอาจไปป์พวกเขา/dev/nullซึ่งเหมือนกัน
aross

ฉันมักจะจำความคิดเห็นที่ผิด :) นี่ไม่ใช่ O (n) ใช่ไหม
ติตัส

ใช่มันเป็นเส้นตรง
aross

วิธีการที่เป็นO(1)พื้นที่เพิ่มเติม? คุณกำลังกำหนดตัวแปรใหม่อย่างแท้จริงต่อ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 การเป็น int จะถูกส่งไปโดยอัตโนมัติในระยะเวลานานโดยไม่ระบุนักแสดงอย่างชัดเจน
SchoolBoy

มันจะเหวี่ยงโดยปริยายlongแต่ไม่ถึงตามที่กำหนดสำหรับแลมบ์ดาที่จะได้รับมอบหมายให้เป็นLong Functionคุณทดสอบหรือไม่ ไม่ว่าโซลูชันนั้นจะถูกแทนที่ด้วยโซลูชันใหม่ของคุณ
จา

คุณสามารถใช้ประเภท raw Set s=new HashSet();เพื่อบันทึก 7 ไบต์ (นอกจากนี้: การนำเข้าjava.util.*;จะต้องรวมอยู่ในจำนวนไบต์ -> +19 ไบต์) คำสั่งส่งคืนสามารถเป็นreturn++jคำสั่ง if-if สามารถลบได้a->{int i=0,j;for(;(a[j=Math.abs(a[i++])-1]*=-1)<0;);return++j;}(-3 ไบต์)
Nevay

2

Brachylogขนาด 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 ขอบคุณสำหรับเคล็ดลับ!
jferard

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 จัดทำดัชนี) เราใช้ประโยชน์จากสิ่งนี้โดยบอกว่าถ้าองค์ประกอบที่ index i เป็นค่าลบเราเคยเห็นมาก่อน

สำหรับแต่ละองค์ประกอบ a ในรายการ n เราปล่อยให้คุณลบค่าสัมบูรณ์ของ a (เราปล่อยให้มันเป็นลบเพราะหลามสามารถทำดัชนีรายการที่มีดัชนีเป็นลบได้และเราก็ต้องทำเช่นนั้น u=abs(a)-1 ) ถ้าองค์ประกอบที่ดัชนี u ในรายการนั้นเป็นลบเราเคยเห็นมาก่อนแล้วจึงสามารถคืนค่า -u ได้ ค่าสัมบูรณ์ของเป็นองค์ประกอบทั้งหมดเป็นบวก) มิฉะนั้นเรากำหนดให้องค์ประกอบที่ index u เป็นค่าลบเพื่อจำไว้ว่าเราเคยเห็นองค์ประกอบของค่า a มาก่อน


งานที่ดี! 65 bytes
musicman523

คุณแน่ใจหรือว่านี่เป็นหน่วยความจำO (1) ? คุณยังคงใช้หน่วยความจำnบิตเพื่อจัดเก็บตัวเลขที่เคยเยี่ยมชมแม้ว่าตัวเลขนั้นจะอยู่ในสัญลักษณ์ สำหรับฉันดูเหมือนว่านี่คือO (n) ที่ปลอมตัว
Wheat Wizard

เทคนิคนี้ใช้พื้นที่O (n) - บิตเครื่องหมาย n หากอาร์เรย์สามารถเก็บค่าได้ระหว่าง1และnเช่นเดียวกับที่ได้รับมาแสดงว่ามันไม่ทำงาน
Oliver Ni

นี่เป็นเพียงการนำเสนอที่คุณเลือกสำหรับตัวเลข หากใช้หมายเลขที่ไม่ได้ลงชื่อนี่เป็นพื้นที่เสริมO (n) หากใช้หมายเลขที่เซ็นชื่อแล้วเครื่องหมายบิตจะมีอยู่แล้วซึ่งหมายถึงพื้นที่เสริมO (1)
Halvard Hummel

ฉันเห็นด้วยกับคุณที่นั่น โดยส่วนตัวแล้วฉันจะให้คุณเลื่อนโดยใช้จำนวนเต็มที่มีลายเซ็นตราบใดที่คุณไม่ได้ใช้บิตบิตมันควรจะเกี่ยวกับอัลกอริทึมที่ไม่ใช่ด้านเทคนิคของระบบ ที่ถูกกล่าวว่าฉันคิดว่าถ้าคุณจะใช้บิตสัญญาณคุณต้องนับพวกเขา ฉันคิดว่าคำตอบนี้ค่อนข้างฉลาด ถ้าฉันโหวตเหลือวันนี้ฉันจะ upvote มันเพื่อต่อต้าน downvote
ข้าวสาลีตัวช่วยสร้าง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.