แก้ปัญหาเลขานุการ


13

เลขานุการปัญหาเป็นปัญหาที่มีชื่อเสียงอธิบายเป็นดังนี้:

  1. คุณต้องการเลขาคนใหม่
  2. คุณมีผู้สมัคร N คนที่สามารถสัมภาษณ์ครั้งละหนึ่งคน
  3. คุณสามารถให้คะแนนผู้สมัครแต่ละคนหลังการสัมภาษณ์ ระบบการให้คะแนนของคุณจะไม่ให้คะแนนเดียวกันกับผู้สมัครสองคน
  4. หลังจากที่คุณสัมภาษณ์ผู้สมัครคุณต้องให้ "ใช่" หรือ "ไม่" ทันที
  5. คุณต้องการผู้สมัครที่มีคะแนนสูงสุด

วิธีการแก้ปัญหาคือการสัมภาษณ์floor(N/e)ผู้สมัครคนแรกและยอมรับผู้สมัครคนแรกที่มีคะแนนสูงกว่าผู้สมัครคนก่อนหน้าทั้งหมด หากไม่มีผู้สมัครคนใดสูงกว่าให้ส่งคืนผู้สมัครคนสุดท้าย ที่น่าสนใจคือสิ่งนี้ให้1/eเปอร์เซ็นต์ ผู้สมัครสูงสุด eหมายถึงจำนวนออยเลอร์ ในการรับค่าของeคุณสามารถใช้ builtin logหรือ hardcode ให้เป็นทศนิยมอย่างน้อย 5 ตำแหน่ง

การป้อนข้อมูล:

2^31-1อาร์เรย์ที่ไม่ว่างเปล่าของจำนวนเต็มไม่ใช่เชิงลบที่ไม่ซ้ำกันไม่เกิน

เอาท์พุท:

จำนวนเต็มที่แสดงถึงตัวเลือกที่ถูกเลือก เพื่อให้ชัดเจนอัลกอริทึมคือ:

  1. ค้นหาองค์ประกอบสูงสุดในfloor(N/e)องค์ประกอบแรกของอาร์เรย์
  2. วนซ้ำองค์ประกอบที่เหลือและส่งกลับองค์ประกอบแรกที่สูงกว่าค่าสูงสุดที่พบในขั้นตอนที่ 1
  3. หากไม่มีองค์ประกอบใดสูงกว่าให้ส่งคืนองค์ประกอบสุดท้าย

ตัวอย่างเช่นสมมติว่าอาร์เรย์ของคุณ[2,7,4,3,9,20]เพื่อให้และN = 6 floor(N/e) = 22 [2,7]องค์ประกอบแรกของอาร์เรย์คือ สูงสุดของการมี[2,7] องค์ประกอบที่เหลือเป็น7 [4,3,9,20]องค์ประกอบแรกที่มากกว่า7คือเพื่อให้เรากลับมา99

กรณีทดสอบ:

[0]         => 0
[100]       => 100
[100, 45]   => 100
[0, 1]      => 0
[45, 100]   => 45
[1, 4, 5]   => 4
[1, 5, 4]   => 5
[5, 4, 1]   => 1
[5, 1, 4]   => 4
[4, 1, 5]   => 5
[56, 7, 37, 73, 90, 59, 65, 61, 29, 16, 47, 77, 60, 8, 1, 76, 36, 68, 34, 17, 23, 26, 12, 82, 52, 88, 45, 89, 94, 81, 3, 24, 43, 55, 38, 33, 15, 92, 79, 87, 14, 75, 41, 98, 31, 58, 53, 72, 39, 30, 2, 0, 49, 99, 28, 50, 80, 91, 83, 27, 64, 71, 93, 95, 11, 21, 6, 66, 51, 85, 48, 62, 22, 74, 69, 63, 86, 57, 97, 32, 84, 4, 18, 46, 20, 42, 25, 35, 9, 10, 19, 40, 54, 67, 70, 5, 44, 13, 78, 96]
=> 98
[10, 68, 52, 48, 81, 39, 85, 54, 3, 21, 31, 59, 28, 64, 42, 90, 79, 12, 63, 41, 58, 57, 13, 43, 74, 76, 94, 51, 99, 67, 49, 14, 6, 96, 18, 17, 32, 73, 56, 7, 16, 60, 61, 26, 86, 72, 20, 62, 4, 83, 15, 55, 70, 29, 23, 35, 77, 98, 92, 22, 38, 5, 50, 82, 1, 84, 93, 97, 65, 37, 45, 71, 25, 11, 19, 75, 78, 44, 46, 2, 53, 36, 0, 47, 88, 24, 80, 66, 87, 40, 69, 27, 9, 8, 91, 89, 34, 33, 95, 30]
=> 30

วิธีการแก้ปัญหาของคุณจะต้องอยู่O(n)ที่ไหนnความยาวของอาร์เรย์ หากภาษาของคุณมีบิวด์อินที่พบว่ามีอาเรย์สูงสุดคุณสามารถสันนิษฐานได้ว่าฟังก์ชั่นนั้นใช้งานได้O(n)(และหวังว่าจะเป็นเช่นนั้น)

ช่องโหว่มาตรฐานมีผลบังคับใช้และนี่คือดังนั้นคำตอบที่สั้นที่สุดในภาษาที่คุณชื่นชอบ!


1
สิ่งที่eควรใช้
Afuous

2
@ voidpigeon ฉันเข้าใจว่ามันเป็นen.wikipedia.org/wiki/E_(mathematical_constant)
Doorknob

1
อ่าตอนนี้ฉันเข้าใจแล้วว่าอัลกอริทึมทำงานอย่างไร ฉันคิดว่าย่อหน้าที่สองของคุณหมายความว่าคุณไม่เคยสัมภาษณ์ผู้สมัครหลังเลิกเรียน (n / e) เลย
Doorknob

1
ฉันถามโดยเฉพาะเพราะในบางภาษามันสั้นกว่าในการกำหนดตัวแปรที่มีความแม่นยำทศนิยม 5 ตำแหน่งมากกว่าที่จะใช้ builtin e(เช่น Python ที่e=2.71828สั้นกว่าimport math;math.E)
Mego

1
หมายเหตุ: `1 / e เปอร์เซ็นต์ของเวลา 'จะไม่ดีจริง ๆ มันน่าจะเป็น 1 / e นั่นคือประมาณ 37% ของเวลา
edc65

คำตอบ:


4

เยลลี่ 13 ไบต์

L:Øe³ḣȯ-Ṁ<i1ị

แน่นอนO (n)อัลกอริทึมหวังว่าO (n)การดำเนินงาน ลองออนไลน์!

มันทำงานอย่างไร

L:Øe³ḣȯ-Ṁ<i1ị  Main link. Argument: A (list of scores)

L              Get the length of A.
 :Øe           Divide the length by e, flooring the result.
    ³ḣ         Retrieve the that many scores from the beginning of A.
      ȯ-       Logical OR; replace an empty list with -1.
        Ṁ      Compute the maximum of those scores.
         <     Compare each score in A with that maximum.
          i1   Find the first index of 1 (0 if not found).
            ị  Retrieve the element of A at that index (the last one if 0).

3

CJam, 20 ไบต์

q~___,1me/i<:e>f>1#=

ทำงานคล้ายกับข้อเสนอแนะของเดนนิส

q~___                     Read array, duplicate three times
      ,                   Consume one to find the length
       1me/i              Push e then divide and take floor
            <             Take that many elements from the list
             :e>          Find maximum (Thanks to Dennis)
                f>        Label array elements larger than this as 1
                  1#      Find the first one (won't be in set of elements we've looked in)
                    =     Take that element from the final copy of the array. -1 gives us the last element as required

$W=ไม่ทำงานในเวลาเชิงเส้น
Dennis

ใช่คุณพูดถูก มีวิธีที่ดีกว่าในการหาค่าสูงสุดใน CJam ที่คุณรู้หรือไม่?
Simmons

1
:e>(ลดลงสูงสุด)
Dennis

@ เดนนิสขอบคุณ!
Simmons

2

Java, 128 118 ไบต์

a->{int c=(int)(a.length/Math.E),i=0,m=-1,t=0;for(;i<a.length;i++){t=a[i];if(i<c)m=t>m?t:m;if(t>m)return t;}return t;}

เยื้อง:

static Function<Integer[], Integer> secretary2 = a -> {
    int c = (int) (a.length/Math.E),     // c = floor(N/E)
        i = 0, m = -1, t = 0;            // declare vars early to save bytes
    for (;i<a.length;i++) {              // for each element of input
        t = a[i];                        // cache element to save bytes
        if (i<c)                         // if before c
            m = t>m ? t : m;             // m = max(m, element)
        if (t>m)                         // if element > m
            return t;                    // return: we've found our best
    }                                    // if never found a good element
    return t;                            // return the last element
};


2

JavaScript (ES6) 64

(a,l=a.length/Math.E,x)=>(a.every(v=>--l>0?x>v?1:x=v:(z=v)<x),z)

น้อย golfed

(
 a, 
 l=a.length/Math.E, // limit for stage 1
 x // init at undefined
)=>(
  a.every(v => --l > 0 // checking for >0 no need to floor
          ? x>v?1:x=v // stage 1, find max in x, always return truthy
          : (z=v)<x ) // stage 2, set z to current value and exit early if z>x
  , z // at last z has the last seen value
)

ทดสอบ

f=(a,l=a.length/Math.E,x)=>(a.every(v=>--l>0?x>v?1:x=v:(z=v)<x),z)

console.log=x=>O.textContent+=x+'\n'

;[ 
 [0], [100], [0,1], [1,2,3],
 [100, 45],
 [45, 100],
 [1, 4, 5],
 [1, 5, 4],
 [5, 4, 1],
 [5, 1, 4],
 [4, 1, 5],   
 [10, 68, 52, 48, 81, 39, 85, 54, 3, 21, 31, 59, 28, 64, 42, 90, 79, 12, 63, 41, 58, 57, 13, 43, 74, 76, 94, 51, 99, 67, 49, 14, 6, 96, 18, 17, 32, 73, 56, 7, 16, 60, 61, 26, 86, 72, 20, 62, 4, 83, 15, 55, 70, 29, 23, 35, 77, 98, 92, 22, 38, 5, 50, 82, 1, 84, 93, 97, 65, 37, 45, 71, 25, 11, 19, 75, 78, 44, 46, 2, 53, 36, 0, 47, 88, 24, 80, 66, 87, 40, 69, 27, 9, 8, 91, 89, 34, 33, 95, 30],
[56, 7, 37, 73, 90, 59, 65, 61, 29, 16, 47, 77, 60, 8, 1, 76, 36, 68, 34, 17, 23, 26, 12, 82, 52, 88, 45, 89, 94, 81, 3, 24, 43, 55, 38, 33, 15, 92, 79, 87, 14, 75, 41, 98, 31, 58, 53, 72, 39, 30, 2, 0, 49, 99, 28, 50, 80, 91, 83, 27, 64, 71, 93, 95, 11, 21, 6, 66, 51, 85, 48, 62, 22, 74, 69, 63, 86, 57, 97, 32, 84, 4, 18, 46, 20, 42, 25, 35, 9, 10, 19, 40, 54, 67, 70, 5, 44, 13, 78, 96]
].forEach(t=>{
  var r=f(t)
  console.log(r+' : '+t)
})
<pre id=O></pre>


1

Ruby, 64 ไบต์

->a{m=a[0...c=a.size/Math::E].max
a[c..-1].find{|n|n>m}||a[-1]}

2
@ Doorknob มันวนลูปผ่านองค์ประกอบชั้นแรก (N / e) หนึ่งครั้งเพื่อหาค่าสูงสุดจากนั้นวนซ้ำส่วนที่เหลือของรายการในกรณีที่แย่ที่สุดเมื่อเปรียบเทียบแต่ละองค์ประกอบกับค่าสูงสุด มีการเปรียบเทียบเพียงหนึ่งรายการต่อองค์ประกอบในทั้งสองส่วน
Afuous

อ่าใช่แล้ว ฉันอ่านผิดและคิดว่าคุณหาค่าสูงสุดในแต่ละรอบซ้ำ
Doorknob

1
ในความเป็นจริงฉันคิดว่ายังคงเป็น O (n) ถ้าคุณเพิ่งทำa.findในขั้นตอนที่สองแม้ว่าจะเห็นได้ชัดว่ามันมีประสิทธิภาพน้อยกว่ามาก
ฮิสโทแคต

1
คุณสามารถใช้(0...c)สำหรับช่วงที่ไม่รวมค
ฮิสโทแคต

@histocrat ใช่มันควรเป็น O (2n) ซึ่งก็คือ O (n)
ไม่ใช่ Charles

1

PARI / GP , 70 ไบต์

นี่อาจมีปัญหากับ gp รุ่นเก่าเมื่อได้รับซิงเกิลตัน แต่ใช้งานได้อย่างน้อยจากการแก้ไข 18487

v->m=vecmax(v[1..t=#v\exp(1)]);for(i=t+1,#v,v[i]>m&&return(v[i]));v[#v]

1

JavaScript (ES6), 79 ไบต์

a=>(m=Math.max(...a.splice(0,a.length/Math.E)),a.slice(a.findIndex(x=>x>m))[0])

ใช้งานได้เพราะfindIndexผลตอบแทน-1จากความล้มเหลว แต่a.slice(-1)[0]คืนองค์ประกอบสุดท้ายของอาร์เรย์ตามที่ต้องการ


1

Python 2, 87 ไบต์

a=input()
t=int(len(a)/2.71828)
m=max(a[:t]+[-1])
for x in a[t:]:
 if x>m:break
print x

ผู้ใช้เข้าสู่อาร์เรย์เป็นรายการโดยมีเครื่องหมายวงเล็บและเครื่องหมายจุลภาค input()คำสั่งของ Python 2 สะดวกที่นี่

ไม่ว่าเราจะยกเลิกกระบวนการก่อนเวลาหรือไม่เราจ้างคนสุดท้ายที่ได้รับการสัมภาษณ์



1

Python 3.5; 110 ไบต์:

def Interview(h):k=max(h[0:int(len(h)/2.71828)-1]);n=max(h[int(len(h)/2.71828)-1:len(h)-1]);return max([k, n])

โดยทั่วไปสิ่งที่กล่าวมาข้างต้นคือการใช้อาร์เรย์ที่จัดเตรียมไว้เป็นครั้งแรก "h" ตราบใดที่มันมีมากกว่า 5 รายการ (ตอนนี้ ... ) ค้นหาค่าสูงสุดในอาร์เรย์แรก (ความยาวของอาร์เรย์ (len (h (h (h)) )) / จำนวนออยเลอร์ (ถึงทศนิยม 5 ตำแหน่ง)) รายการของอาร์เรย์นั้นแล้วส่งกลับค่านั้นเป็น "k" นอกจากนี้ "n" เป็นค่าสูงสุดในส่วนที่เหลือของอาร์เรย์ สุดท้ายค่าที่ส่งคืนจากฟังก์ชันคือค่าสูงสุดในอาร์เรย์ที่มีทั้ง "k" และ "n"

หมายเหตุ: max()ฟังก์ชั่นของ Python คือความซับซ้อน O (n)

ข้างล่างนี้คืออ่านได้มากขึ้นไม่ใช่รหัสกอล์ฟ รุ่นของโค้ดข้างต้นที่มีการสุ่มอาร์เรย์ 10 รายการที่ไม่ซ้ำกันให้เพื่อยืนยันว่าการทำงาน:

import random, math

def Interview():
    k = max(h[0:int(len(h)/math.e)-1])
    n = max(h[int(len(h)/math.e)-1:len(h)-1])
    return max([k, n])

h = random.sample(range((2*31)-1), 10)

print(Interview(h))

ยินดีต้อนรับสู่ PPCG! คุณสามารถใช้เครื่องหมายจุลภาคคั่นการนำเข้าของคุณ นอกจากนี้คุณไม่จำเป็นต้องสร้างอาเรย์ด้วยตัวเองเพื่อให้คุณสามารถลบส่วนของรหัสนั้น (เพียงแค่มีอาเรย์เป็นพารามิเตอร์ในฟังก์ชั่น)
นาธานเมอร์ริลล์

@NathanMerrill ใช่ฉันกำลังคิดที่จะทำสิ่งนั้น แต่ฉันคิดว่าคุณจะไม่ชอบมันจริงๆ แต่ตอนนี้ฉันรู้ว่าไม่สำคัญจริงๆฉันจะแก้ไขคำตอบของฉัน นอกจากนี้ขอขอบคุณสำหรับเคล็ดลับเกี่ยวกับเครื่องหมายจุลภาคเพื่อแยกการนำเข้าของฉัน ฉันลืมไปหมดเลย!
R. Kap

เคล็ดลับอื่น ๆ : คุณมีช่องว่างที่ไม่จำเป็นจำนวนมาก (หลังจากเครื่องหมายจุลภาคระหว่างเครื่องหมายเท่ากับคุณไม่จำเป็นต้องพิมพ์คำสั่งในตอนท้ายเช่นกัน
นาธานเมอร์ริลล์

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