n명이 입국심사를 위해 줄을 서서 기다리고 있습니다. 각 입국심사대에 있는 심사관마다 심사하는데 걸리는 시간은 다릅니다.
처음에 모든 심사대는 비어있습니다. 한 심사대에서는 동시에 한 명만 심사를 할 수 있습니다. 가장 앞에 서 있는 사람은 비어 있는 심사대로 가서 심사를 받을 수 있습니다. 하지만 더 빨리 끝나는 심사대가 있으면 기다렸다가 그곳으로 가서 심사를 받을 수도 있습니다.
모든 사람이 심사를 받는데 걸리는 시간을 최소로 하고 싶습니다.
입국심사를 기다리는 사람 수 n, 각 심사관이 한 명을 심사하는데 걸리는 시간이 담긴 배열 times가 매개변수로 주어질 때, 모든 사람이 심사를 받는데 걸리는 시간의 최솟값을 return 하도록 solution 함수를 작성해주세요.
n | times | return |
---|---|---|
6 | [7, 10] | 28 |
가장 첫 두 사람은 바로 심사를 받으러 갑니다.
7분이 되었을 때, 첫 번째 심사대가 비고 3번째 사람이 심사를 받습니다.
10분이 되었을 때, 두 번째 심사대가 비고 4번째 사람이 심사를 받습니다.
14분이 되었을 때, 첫 번째 심사대가 비고 5번째 사람이 심사를 받습니다.
20분이 되었을 때, 두 번째 심사대가 비지만 6번째 사람이 그곳에서 심사를 받지 않고 1분을 더 기다린 후에 첫 번째 심사대에서 심사를 받으면 28분에 모든 사람의 심사가 끝납니다.
def solution(n, times):
answer = 0
times.sort()
lt = 1
rt = times[-1] * n
while lt <= rt:
mid = (lt + rt) // 2
v = 0
for t in times:
v += mid // t
if v > n:
break
if v >= n:
rt = mid - 1
answer = mid
else:
lt = mid + 1
return answer
이분탐색은 최댓값, 최솟값을 정하는 것이 중요하다.
여기서는 lt
는 최솟값이고 rt
는 최댓값이다. 근데 어떤것의 최솟값이고 최댓값인지 그것을 정하는게 중요하다.
이 문제에서는 최종적으로 구하는 것이 모든 사람이 심사를 받는 데 걸리는 시간의 최솟값이기 때문에, 심사를 받는데 걸리는 시간의 최솟값과 최댓값을 lt
, rt
로 놓는다.
rt
는 심사시간이 가장 오래 걸리는 사람이 혼자 모든 심사를 하는 경우의 시간을 넣는다. times
를 오름차순으로 sort하여 마지막 원소 * n
을 하면 된다.
rt
를 위와 같이 했다고 lt
도 가장 빠른사람 * n
을 하면 안된다. lt
가 가장 빠르더라도 다른사람과 함께 하면 더 빨리 끝나는 경우도 있기 때문이다. 그리고 심사 받는사람 n
이 심사관들보다 같거나 적고 심사관들이 모두 1분만에 심사를 끝낸다면 1분만에 모든 사람들의 심사가 끝난다. lt
는 1로 놓자.
이제 while문에서 값을 구할 차례이다.
중간값 mid
를 (lt + rt) // 2
로 구하고, 이 시간(mid
)동안에 모든 심사위원들이 몇명의 사람을 심사할 수 있는지 구한다. (v
)
만약 v
가 n
보다 크거나 같다면 mid
는 n
명 이상을 심사할 수 있다는 뜻이다. 우리는 n명을 심사하는 시간의 최솟값
을 구해야 하기 때문에 rt = mid - 1
을 해주고 answer
은 mid
값을 넣어는다.
만약 v
가 n
보다 작다면 mid
는 n
명 미만을 심사할 수 있다는 뜻이다. 그렇다면 n
명을 심사하기에는 mid
시간으로는 부족하기에 더 필요하다. 따라서 lt = mid + 1
을 해주고 while문을 계속 진행한다.
계속 진행하다보면 lt
가 rt
보다 커지는 경우가 있다. 이 경우에 while문을 빠져나오고, 마지막으로 v
가 n
보다 크거나 같았을 경우의 mid
값이 answer
에 저장되어있다. 이 값이 n명을 심사하는 최소 시간이다.