Sekreter Sorunu Çöz


13

Sekreter Sorun şöyle anlatılabilir ünlü bir sorundur:

  1. Yeni bir sekretere ihtiyacınız var
  2. Bir kerede bir görüşme yapabileceğiniz N adayınız var
  3. Mülakattan sonra her adayı puanlayabilirsiniz. Puanlama sisteminiz asla iki başvuru sahibine aynı puanı vermeyecektir
  4. Bir başvuru sahibiyle görüştükten sonra, derhal bir "evet" veya "hayır"
  5. En yüksek puanı alan başvuru sahibini istiyorsunuz

Çözüm, ilk floor(N/e)başvuru sahipleriyle görüşmek ve ardından önceki başvuru sahiplerinden daha yüksek puanı alan ilk başvuru sahibini kabul etmektir. Başvuru sahiplerinden hiçbiri daha yüksek değilse, son başvuru sahibini iade edin. İlginçtir ki, bu en iyi başvuru sahibine 1/ezamanın yüzdesini verir . Euler numarasınıe ifade eder . Değerini elde etmek için bir yerleşkeyi kullanabilir veya en az 5 ondalık basamağa sabit kodlayabilirsiniz.elog

Giriş:

Boş olmayan benzersiz negatif olmayan tamsayılar dizisi en fazla 2^31-1.

Çıktı:

Seçilen adayı temsil eden bir tam sayı. Açık olmak gerekirse algoritma:

  1. floor(N/e)Dizinin ilk öğelerinde maksimum öğeyi bulun .
  2. Kalan öğeler arasında yineleme yapın ve 1. adımda bulunan maksimum değerden daha yüksek olan ilk öğeyi döndürün.
  3. Elemanların hiçbiri daha yüksek değilse, son elemanı döndürmektense.

Örneğin, dizi olduğunu söylemek [2,7,4,3,9,20]bu yüzden, N = 6ve floor(N/e) = 2. Dizinin ilk 2 öğesi [2,7]. Maksimum [2,7]DİR 7. Kalan elemanlar [4,3,9,20]. Daha büyüktür birinci unsur 7olduğunu 9, bu yüzden dönmek 9.

Test Durumları:

[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

Çözümünüz , dizinin uzunluğu O(n)nerede olmalıdır n. Dilinizde bir dizinin maksimumu bulan bir yerleşik varsa, işlevin alındığını varsayabilirsiniz O(n)(ve umarım yapar).

Standart boşluklar uygulanır ve bu bir , bu yüzden en sevdiğiniz dilde en kısa cevabı verin!


1
Ne ekullanılmalı?
16'da ateşli


1
Ah, şimdi algoritmanın nasıl çalıştığını anlıyorum. İkinci paragrafınızın kattan sonra (n / e) adaylarla asla röportaj yapmamanız anlamına geldiğini düşündüm.
Kapı tokmağı

1
Bazı dillerde, bu aslında yerleşiğini kullanmaktır daha hassas 5 ondalık noktaları ile bir değişken tanımlamak için kısa olduğu için özellikle sordum e(örn Python, e=2.71828daha kısadır import math;math.E)
Mego

1
Not: `` Zamanın yüzde 1 / e'si. '' Gerçekten kötü olurdu. 1 / e olasılık, kabaca% 37 oranındadır
edc65

Yanıtlar:


4

Jöle, 13 bayt

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

Kesinlikle bir O (n) algoritması, umarım bir O (n) uygulamasıdır. Çevrimiçi deneyin!

Nasıl çalışır

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 Bayt

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

Dennis'in önerisine benzer şekilde çalışır.

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=doğrusal zamanda çalışmaz.
Dennis

Urgh, haklısın. CJam'de bunun bildiğiniz maksimum değeri bulmanın daha iyi bir yolu var mı?
Bir Simmons

1
:e>(maksimumda azalma)
Dennis

@Dennis Teşekkürler!
Bir Simmons

2

Java, 128 118 bayt

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

Girintili'ye:

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)

Daha az golf

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

Ölçek

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 bayt

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

2
@ Kapı Düğmesi Maksimum değeri bulmak için birinci kat (N / e) öğelerini bir kez, daha sonra her bir öğeyi maksimumla karşılaştırarak en kötü durumda listenin geri kalanını döndürür. Her iki parçada da eleman başına sadece bir karşılaştırma vardır.
17'de ateşli

Ah, doğru. Yanlış okudum ve her yinelemede maksimumu bulduğunu düşündüm.
Kapı tokmağı

1
Aslında, sadece a.findikinci adımda yapıyorsanız hala O (n) olduğunu düşünüyorum , ancak çok daha az verimli olmasına rağmen.
histokrat

1
(0...c)Hariç tutulan bir aralık için kullanabilirsiniz c.
histokrat

@histokrat Evet, O (2n), O (n) olmalı
Charles

1

PARI / GP , 70 bayt

Bu, bir singleton verildiğinde gp'nin eski sürümlerinde sorun yaşayabilir, ancak en azından 18487 revizyonundan itibaren çalışır.

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 bayt

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

Başarısızlıkla findIndexdöndürdüğü -1için çalışır , ancak a.slice(-1)[0]dizinin son öğesini istediğiniz gibi döndürür.


1

Python 2, 87 bayt

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

Kullanıcı diziyi köşeli parantez ve virgüllerle liste olarak girer. Python 2'nin input()komutu burada kullanışlıdır.

Süreci erken sonlansak da bitirmesek de görüşülen son kişiyi işe alırız.



1

Python 3.5; 110 bayt:

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])

Temel olarak, yukarıdakilerin yaptığı, ilk olarak sağlanan bir diziyi almasıdır, 5'ten fazla öğe içerdiği sürece (şimdilik ...), "dizinin uzunluğu" (len (h )) / Euler sayısı (5 ondalık basamağa kadar)) ve bu değeri "k" olarak döndürür. Ayrıca, "n" dizinin geri kalanındaki maksimum değerdir. Son olarak, işlevden döndürülen değer hem "k" hem de "n" içeren bir dizideki maksimum değerdir.

Not: max()Python'un işlevi O (n) karmaşıklığıdır.

Aşağıda, çalıştığından emin olmak için yukarıdaki kodun rastgele, benzersiz bir 10 öğe dizisi bulunan daha okunabilir, kodsuz bir golf sürümü bulunmaktadır:

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'ye Hoşgeldiniz! İthalatlarınızı virgülle ayırabilirsiniz. Ayrıca, diziyi kendiniz oluşturmanıza gerek yoktur, böylece kodun bu bölümünü kaldırabilirsiniz (diziyi işleve bir parametre olarak atabilirsiniz)
Nathan Merrill

@NathanMerrill Evet, bunu yapmayı düşünüyordum, ama sonra gerçekten sevmeyeceğini düşündüm, ama şimdi bunun gerçekten önemli olmadığını bildiğime göre, cevabımı düzenleyeceğim. Ayrıca, ithalatımı ayıran virgülle ilgili ipucu için teşekkürler. Bunu tamamen unutmuştum!
R. Kap

Diğer ipuçları: Çok fazla gereksiz boşluk var (virgülden sonra, eşittir işaretleri arasında. Sonunda bir yazılı açıklamaya da ihtiyacınız yok.
Nathan Merrill

@NathanMerrill İpuçları için teşekkürler! Daha fazla kod golf yaparken bunları aklımda tutacağım! :)
R. Kap
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.