문제
n명이 입국심사를 위해 줄을 서서 기다리고 있습니다. 각 입국심사대에 있는 심사관마다 심사하는데 걸리는 시간은 다릅니다.
처음에 모든 심사대는 비어있습니다. 한 심사대에서는 동시에 한 명만 심사를 할 수 있습니다. 가장 앞에 서 있는 사람은 비어 있는 심사대로 가서 심사를 받을 수 있습니다. 하지만 더 빨리 끝나는 심사대가 있으면 기다렸다가 그곳으로 가서 심사를 받을 수도 있습니다.
모든 사람이 심사를 받는데 걸리는 시간을 최소로 하고 싶습니다.
입국심사를 기다리는 사람 수 n, 각 심사관이 한 명을 심사하는데 걸리는 시간이 담긴 배열 times가 매개변수로 주어질 때, 모든 사람이 심사를 받는데 걸리는 시간의 최솟값을 return 하도록 solution 함수를 작성해주세요.
제한사항
입국심사를 기다리는 사람은 1명 이상 1,000,000,000명 이하입니다.
각 심사관이 한 명을 심사하는데 걸리는 시간은 1분 이상 1,000,000,000분 이하입니다.
심사관은 1명 이상 100,000명 이하입니다.
접근법
문제 예시에서
- 20분이 되었을 때, 두 번째 심사대가 비지만 6번째 사람이 그곳에서 심사를 받지 않고 1분을 더 기다린 후에 첫 번째 심사대에서 심사를 받으면 28분에 모든 사람의 심사가 끝납니다.
이 말 때문에 그러면 사람 한명씩 심사를 어디서 받아야 유리한지 계속 체크해주면서 가야하나? 싶었지만 생각해보면 그럴 필요가 없는게
28분 - 7분 걸리는 곳 4명 끝 + 10분 걸리는 곳 2명 끝 = 6명 끝 이기 때문에
'모든 사람이 심사를 받는데 걸리는 시간'을 기준으로 이 시간 안에 n명이 심사를 받을 수 있는지?를 구해주면 됨 - times 배열의 최댓값이 10억이기 때문에 이분탐색을 통해 log n까지는 줄여야 함
풀이
'모든 사람이 심사를 받는데 걸리는 시간'의 최댓값은 '가장 오래 걸리는 심사시간 * n'이라고 할 수 있음
그러면 최댓값부터 시작해서 이 시간동안 n명이 받을 수 있다면 점점 값을 줄여가면서 구해주면 되지만 범위가 매우 크기 때문에 이분탐색을 이용해 주면됨
Ex)
최대+최소/2로 mid 값을 구한 다음
mid시간 동안 n명을 조사할 수 있는가?를 구하면 됨
예시처럼 [7,10]이 있고, n=6이라면 mid는 31 => 7분 걸리는 곳에서 4명 + 10분 걸리는 곳에서 2명 >= 6명 이기 때문에 31은 가능한 값
가능한 값이 나오면 end = mid-1로 놓고 다시 구해서, start>end가 되기 전까지 구해주면 됨
코드
function solution(n, times) {
times.sort((a,b) => a - b)
let [start,end] = [1,times.at(-1)*n]
let answer = end
while(start<=end){
let count = 0
let mid = Math.floor((start+end)/2)
for(let time of times){
count += Math.floor(mid/time)//mid라는 전체 시간동안 time이 걸리는 심사대에서 몇명이 심사받을 수 있는지
if(count>=n){
answer = Math.min(answer,mid)
break}
}
if(count>=n){
end = mid-1
}
if(count<n){
start = mid + 1
}
}
return answer
}
'코딩테스트 연습' 카테고리의 다른 글
프로그래머스 - 귤 고르기 JS (0) | 2023.07.28 |
---|---|
프로그래머스 - 수식 최대화 JS (0) | 2023.07.24 |
프로그래머스 - 부대복귀 JS (0) | 2023.06.26 |
백준 1411 - 비슷한 단어 JS (0) | 2023.06.16 |
백준 2309 - 일곱 난쟁이 JS (0) | 2023.06.16 |