Giải quyết vấn đề thư ký


13

Các Bộ trưởng Vấn đề là một vấn đề nổi tiếng miêu tả là như sau:

  1. Bạn cần một thư ký mới
  2. Bạn có N ứng viên mà bạn có thể phỏng vấn cùng một lúc
  3. Bạn có thể chấm điểm từng ứng viên sau cuộc phỏng vấn. Hệ thống tính điểm của bạn sẽ không bao giờ cho hai ứng viên cùng số điểm
  4. Sau khi bạn phỏng vấn ứng viên, bạn phải đưa ra "có" hoặc "không" ngay lập tức
  5. Bạn muốn ứng viên có số điểm cao nhất

Giải pháp là phỏng vấn những floor(N/e)người nộp đơn đầu tiên , và sau đó chấp nhận người nộp đơn đầu tiên có điểm cao hơn tất cả những người nộp đơn trước đó. Nếu không có ứng viên nào cao hơn, thì hãy trả lại người nộp đơn cuối cùng. Thật thú vị, điều này mang lại cho 1/ephần trăm ứng viên hàng đầu thời gian. eđề cập đến số của Euler . Để có được giá trị của e, bạn có thể sử dụng nội dung loghoặc mã hóa cứng đến ít nhất 5 điểm thập phân.

Đầu vào:

Một mảng không trống của các số nguyên không âm duy nhất không quá 2^31-1.

Đầu ra:

Một số nguyên đại diện cho ứng cử viên được chọn. Để rõ ràng thuật toán là:

  1. Tìm phần tử tối đa trong các floor(N/e)phần tử đầu tiên của mảng.
  2. Lặp lại qua các phần tử còn lại và trả về phần tử đầu tiên cao hơn mức tối đa được tìm thấy ở bước 1.
  3. Nếu không có phần tử nào cao hơn, trả về phần tử cuối cùng.

Ví dụ, giả sử mảng của bạn là [2,7,4,3,9,20], vì vậy N = 6floor(N/e) = 2. 2 phần tử đầu tiên của mảng là [2,7]. Tối đa [2,7]7. Các yếu tố còn lại là [4,3,9,20]. Yếu tố đầu tiên lớn hơn 79, vì vậy chúng tôi trở lại 9.

Các trường hợp thử nghiệm:

[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

Giải pháp của bạn phải là O(n), nchiều dài của mảng. Nếu ngôn ngữ của bạn có nội dung tìm thấy tối đa của một mảng, bạn có thể giả sử rằng hàm đó có O(n)(và hy vọng là có).

Các sơ hở tiêu chuẩn được áp dụng, và đây là một , vì vậy hãy đưa ra câu trả lời ngắn nhất bằng ngôn ngữ yêu thích của bạn!


1
Có gì enên được sử dụng?
afuous

2
@voidpigeon Tôi đoán đó là en.wikipedia.org/wiki/E_(mathologists_constant)
Doorknob

1
Ah, bây giờ tôi hiểu làm thế nào các thuật toán hoạt động. Tôi nghĩ rằng đoạn thứ hai của bạn có nghĩa là bạn không bao giờ phỏng vấn các ứng cử viên sau khi lên sàn (n / e) cả.
Doorknob

1
Tôi đã hỏi cụ thể bởi vì trong một số ngôn ngữ, việc xác định một biến có 5 điểm thập phân có độ chính xác ngắn hơn so với thực tế là sử dụng phần dựng sẵn e(ví dụ: Python, nơi e=2.71828ngắn hơn import math;math.E)
Mego

1
Lưu ý: `1 / e phần trăm thời gian. 'Sẽ thực sự tồi tệ. Đó là xác suất 1 / e, tức là khoảng 37% số lần
edc65

Câu trả lời:


4

Thạch, 13 byte

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

Chắc chắn là một thuật toán O (n) , hy vọng việc triển khai O (n) . Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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 byte

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

Hoạt động tương tự như đề xuất của Dennis.

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=không chạy trong thời gian tuyến tính.
Dennis

Urgh, bạn đã đúng. Có cách nào tốt hơn để tìm tối đa trong CJam mà bạn biết không?
Một Simmons

1
:e>(giảm tối đa)
Dennis

@Dennis Cảm ơn!
Một Simmons

2

Java, 128 118 byte

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

Thụt lề:

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)

Ít chơi gôn

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

Kiểm tra

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 byte

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

2
@Doorknob Nó lặp qua các phần tử (N / e) tầng một một lần để tìm mức tối đa, sau đó lặp qua phần còn lại của danh sách trong trường hợp xấu nhất so sánh từng phần tử với mức tối đa. Chỉ có một so sánh cho mỗi yếu tố trong cả hai phần.
afuous

À, đúng rồi. Tôi đã đọc sai và nghĩ rằng bạn đang tìm kiếm tối đa trong mỗi lần lặp.
Doorknob

1
Trên thực tế, tôi nghĩ vẫn là O (n) nếu bạn chỉ làm a.findtrong bước thứ hai, mặc dù rõ ràng nó kém hiệu quả hơn rất nhiều.
lịch sử

1
Bạn có thể sử dụng (0...c)cho một phạm vi loại trừ c.
lịch sử

@histocrat Vâng, nó phải là O (2n) là O (n)
Không phải Charles

1

PARI / GP , 70 byte

Điều này có thể gặp sự cố trên các phiên bản cũ của gp khi được cung cấp một đĩa đơn, nhưng nó hoạt động ít nhất từ ​​phiên bản 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 byte

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

Hoạt động vì findIndextrả về -1khi thất bại, nhưng a.slice(-1)[0]trả về phần tử cuối cùng của mảng như mong muốn.


1

Python 2, 87 byte

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

Người dùng nhập vào mảng dưới dạng một danh sách, với dấu ngoặc vuông và dấu phẩy. input()Lệnh của Python 2 thuận tiện ở đây.

Cho dù chúng tôi có chấm dứt quá trình sớm hay không, chúng tôi thuê người cuối cùng được phỏng vấn.


1

Perl 6, 43 byte

Tôi nghĩ rằng đây là O (n)

{@^a.first(*>max @a[^floor @a/e])//@a[*-1]}

1

Con trăn 3,5; 110 byte:

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

Về cơ bản, những gì ở trên là trước tiên nó lấy một mảng được cung cấp, "h" miễn là nó bao gồm hơn 5 mục (hiện tại ...), tìm giá trị tối đa trong đầu tiên (độ dài của mảng (len (h) )) / Số Euler (đến 5 chữ số thập phân)) các mục của mảng đó và sau đó trả về giá trị đó là "k". Hơn nữa, "n" là giá trị tối đa trong phần còn lại của mảng. Cuối cùng, giá trị được trả về từ hàm là giá trị tối đa trong một mảng chứa cả "k" và "n".

Lưu ý: max()Chức năng của Python độ phức tạp O (n).

Dưới đây là phiên bản golf không mã , dễ đọc hơn của mã trên có một mảng 10 mục ngẫu nhiên, duy nhất được cung cấp, để xác nhận rằng nó hoạt động:

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

Chào mừng đến với PPCG! Bạn có thể dấu phẩy riêng biệt nhập khẩu của bạn. Ngoài ra, bạn không cần phải tự tạo mảng, vì vậy bạn có thể xóa phần mã đó (chỉ cần có mảng làm tham số cho hàm)
Nathan Merrill

@NathanMerrill Vâng, tôi đã nghĩ đến việc đó, nhưng sau đó tôi nghĩ rằng bạn sẽ không thực sự thích nó, nhưng bây giờ tôi biết điều đó thực sự không quan trọng, tôi sẽ chỉnh sửa câu trả lời của mình. Ngoài ra, cảm ơn vì lời khuyên về dấu phẩy phân tách hàng nhập khẩu của tôi. Tôi đã hoàn toàn quên mất điều đó!
R. Kap

Các mẹo khác: Bạn có rất nhiều khoảng trắng không cần thiết (sau dấu phẩy, giữa các dấu bằng. Bạn cũng không cần một câu lệnh in ở cuối.
Nathan Merrill

@NathanMerrill Cảm ơn những lời khuyên! Tôi sẽ ghi nhớ những điều đó khi tôi chơi golf nhiều hơn! :)
R. Kap
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.