Розв’яжіть задачу секретаря


13

Секретар Проблема відома проблема описана як таким чином:

  1. Вам потрібен новий секретар
  2. У вас є N заявників, які можете взяти інтерв'ю один за одним
  3. Ви можете оцінити кожного кандидата після співбесіди. Ваша система балів ніколи не дасть двом претендентам однакову оцінку
  4. Після співбесіди з заявником ви повинні дати негайне "так" або "ні"
  5. Ви хочете, щоб заявник мав найвищий бал

Рішення полягає в опитуванні перших floor(N/e)заявників, а потім прийнятті першого заявника, який має більш високий бал, ніж усі попередні заявники. Якщо жоден із заявників вищий, поверніть останнього заявника. Цікаво, що це надає 1/eвідсоткам часу найкращому заявнику . eпосилається на номер Ейлера . Щоб отримати значення e, ви можете використовувати вбудований logабо жорсткий код, принаймні до 5 знаків після коми.

Вхід:

Непорожній масив унікальних невід’ємних цілих чисел не більше 2^31-1.

Вихід:

Ціле число, що представляє обраного кандидата. Щоб зрозуміти алгоритм:

  1. Знайдіть максимальний елемент у перших floor(N/e)елементах масиву.
  2. Ітерайте через інші елементи та поверніть перший елемент, який перевищує максимум, знайдений на кроці 1.
  3. Якщо жоден з елементів не вище, поверніть останній елемент.

Наприклад, скажіть, ваш масив був [2,7,4,3,9,20], так N = 6і floor(N/e) = 2. Перші 2 елементи масиву є [2,7]. Макс [2,7]є 7. Решта елементів є [4,3,9,20]. Перший елемент, який більший, ніж 7є 9, тому ми повертаємось 9.

Випробування:

[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слід використовувати?
невдалий

2
@voidpigeon Я припускаю, що це en.wikipedia.org/wiki/E_(mathematical_constant)
Doorknob

1
Ах, тепер я розумію, як працює алгоритм. Я подумав, що ваш другий абзац означає, що ви взагалі ніколи не опитуєте кандидатів після рейтингу (п / е).
Дверна ручка

1
Я запитав конкретно, тому що в деяких мовах коротше визначити змінну з 5-ма точними точністю, ніж реально використовувати вбудований e(наприклад, Python, де e=2.71828коротше import math;math.E)
Mego

1
Примітка: "1 / е відсотків часу". Було б дуже погано. Це ймовірність 1 / е, тобто приблизно 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=не працює в лінійний час.
Денніс

Ургу, ти маєш рацію. Чи є кращий спосіб знайти максимум в CJam, який ви знаєте про це?
Сіммонс

1
:e>(зменшити на максимум)
Денніс

@Dennis Дякую!
Сіммонс

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)

Менше гольфу

(
 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

Рубін, 64 байти

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

2
@Doorknob Один раз проходить елементи першого поверху (N / e), щоб знайти максимум, а потім прокручує решту списку, в гіршому випадку, порівнюючи кожен елемент з максимумом. Існує лише одне порівняння на елемент в обох частинах.
невдалий

Ага, саме так. Я неправильно прочитав і подумав, що ви знаходите максимум у кожній ітерації.
Дверна ручка

1
Насправді, я думаю, що це все-таки O (n), якщо ви просто зробите a.findна другому кроці, хоча, очевидно, це набагато менш ефективно.
гістократ

1
Ви можете використовувати (0...c)для діапазону, що виключає c.
гістократ

@histocrat Так, це повинен бути O (2n), який є O (n)
Не те, щоб Чарльз

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) )) / Число Ейлера (до 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! Ви можете відокремити комою імпорт. Крім того, вам не потрібно самостійно генерувати масив, тож ви можете видалити цю частину коду (просто матрицю майте як параметр функції)
Nathan Merrill

@NathanMerrill Так, я думав це зробити, але тоді я подумав, що тобі це не дуже сподобається, але тепер, коли я знаю, що це насправді не має значення, я відредагую свою відповідь. Також дякую за пораду щодо кома, яка розділяє мій імпорт. Я зовсім забув про це!
Р. Кап

Інші поради: у вас багато непотрібних пробілів (після коми, між знаками рівних. Вам також не потрібна друкована заява в кінці.
Nathan Merrill

@NathanMerrill Дякую за поради! Я буду тримати це на увазі, коли більше займаюся гольф-кодом! :)
Р. Кап
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.