Lv3. 입국심사

이분탐색 > 입국심사

프로그래머스 문제

문제 설명

n명이 입국심사를 위해 줄을 서서 기다리고 있습니다. 각 입국심사대에 있는 심사관마다 심사하는데 걸리는 시간은 다릅니다.

처음에 모든 심사대는 비어있습니다. 한 심사대에서는 동시에 한 명만 심사를 할 수 있습니다. 가장 앞에 서 있는 사람은 비어 있는 심사대로 가서 심사를 받을 수 있습니다. 하지만 더 빨리 끝나는 심사대가 있으면 기다렸다가 그곳으로 가서 심사를 받을 수도 있습니다.

모든 사람이 심사를 받는데 걸리는 시간을 최소로 하고 싶습니다.

입국심사를 기다리는 사람 수 n, 각 심사관이 한 명을 심사하는데 걸리는 시간이 담긴 배열 times가 매개변수로 주어질 때, 모든 사람이 심사를 받는데 걸리는 시간의 최솟값을 return 하도록 solution 함수를 작성해주세요.

제한사항

  • 입국심사를 기다리는 사람은 1명 이상 1,000,000,000명 이하입니다.
  • 각 심사관이 한 명을 심사하는데 걸리는 시간은 1분 이상 1,000,000,000분 이하입니다.
  • 심사관은 1명 이상 100,000명 이하입니다.

시각화

n 이 6이라는 것은 6명이 입국심사를 받아야 한다는 것이다.

times 가 [7, 10] 이라는 것은 각 심사관이 7분, 10분이 걸린다는 것이다.

이 때 6명을 처리할 때 아래와 같이 처리하여 28분이 소요된다.

입국심사-1.png

n 이 6 이면서 times 가 [7, 10, 10] 경우는 아래와 같이 20분이 소요된다.

입국심사-2.png

n 이 6 이면서 times 가 [2, 3] 경우는 아래와 같이 8분이 소요된다. 이 케이스로 문제 해결 과정을 설명하겠다.

입국심사-3.png

문제 해결 과정

문제를 풀 때 시각화한 것처럼 배열을 만들어서 풀려고하였다. 정답이건 오답이건 시간 초과를 해결할 기미가 보이지 않았다. 제한 사항을 보면 n 의 최대 크기는 1억이다. 즉 비어있는 for 문만 1억 번 돌아도 시간 초과가 발생한다.

알고리즘을 풀 때 자주 느끼는 것은 문제 해결할 때 어떤 값을 관점으로 두고 풀 것이냐가 중요하다고 생각될 때가 많다. 이번 경우에는 이분 탐색인 것은 감이 왔지만 관점을 잘못 두어서 고생을 좀 하였던 것 같다.

이제 문제를 해결 해보자.

아래를 보면 1 ~ 18이 있는데 이 값은 제일 오래 걸리는 심사관의 소요 시간 * n 이다. 즉 최대 시간이다. 다시 말해 제일 오래 걸리는 사람이 모든 사람을 심사하는 경우이다.

입국심사-4.png

심사관 2명은 2, 3 분 씩 걸리기에 시간 별로 처리할 수 있는 사람 수를 아래와 같이 구할 수 있다. 그 값을 다 더하면 각 시간에 몇 명을 처리할 수 있는지 알 수 있다.

입국심사-5.png

우리는 6명을 처리할 수 있을 때의 시간을 구하고 싶다.

입국심사-6.png

시간을 1부터 증가시켜 값을 계산할 수는 없기 때문에 이럴 때 이분 탐색을 통해 효율적으로 값을 구할 수 있다.

L = 1, R = 18

M = 9

입국심사-7.png

시간 9의 값은 찾고자 하는 값보다 크므로 R 을 조정한다.

L = 1, R = 8 (M - 1)

M = 4

입국심사-8.png

찾고자 하는 값보다 작으므로 L 을 조정한다.

L = 5 (M + 1), R = 8

M = 6

입국심사-9.png

L = 7 (M + 1), R = 8

M = 7

입국심사-10.png

마지막으로 L 을 조정하면 6명을 처리할 수 있는 최소 시간이 나온다.

L = 8 (M + 1), R = 8

M = 8

입국심사-12.png

전체 코드

def solution(n, times):
    left = 1
    right = max(times) * n
    answer = right

    while left <= right:
        mid = (left + right) // 2

        if sum(mid // time for time in times) >= n:
            answer = mid
            right = mid - 1
        else:
            left = mid + 1

    return answer


print(solution(6, [7, 10, 10]), 20)
print(solution(6, [2, 3]), 8)  
print(solution(6, [7, 10]), 28)

입국심사-11.png


Lv3. 연속 펄스 부분 수열의 합

수레 움직이기

Lv2. 2개 이하로 다른 비트

월간 코드 챌린지 시즌2 > 2개 이하로 다른 비트

NCloud LB & SourcePipeline 구축하기
tech collection 서비스 성능 개선하기
Selenium 복권 구매 자동화 만들어보기
디자인 패턴
책 리뷰
블로그 챌린지