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


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.