It's easy, if you try

[프로그래머스] 입국심사 (Python) / 이분탐색 본문

알고리즘/파이썬(Python)

[프로그래머스] 입국심사 (Python) / 이분탐색

s5he2 2021. 7. 3. 01:11

문제

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

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

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

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

제한사항

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

입출력 예

ntimesreturn

6 [7, 10] 28

입출력 예 설명

가장 첫 두 사람은 바로 심사를 받으러 갑니다.

7분이 되었을 때, 첫 번째 심사대가 비고 3번째 사람이 심사를 받습니다.

10분이 되었을 때, 두 번째 심사대가 비고 4번째 사람이 심사를 받습니다.

14분이 되었을 때, 첫 번째 심사대가 비고 5번째 사람이 심사를 받습니다.

20분이 되었을 때, 두 번째 심사대가 비지만 6번째 사람이 그곳에서 심사를 받지 않고 1분을 더 기다린 후에 첫 번째 심사대에서 심사를 받으면 28분에 모든 사람의 심사가 끝납니다.

풀이

이분 탐색을 이용하여 푸는 문제이다.

이분 탐색(이진 탐색)이란

동영상을 보면 이분 탐색에 대한 이해가 쉬울 것이다!

링크 : https://www.youtube.com/watch?v=SKcG0p73yo4

이분 탐색은 탐색 기법 중 하나로써 원하는 탐색 범위를 두 부분으로 분할해서 찾는 방식이다. 탐색 범위는 반드시 정렬되어 있어야 한다. 전체 탐색에 비해 속도가 빠르다.

탐색 범위의 처음(left)과 끝(right)의 중간(mid)과 탐색하고자 하는 값을 비교하여

  1. 탐색 값이 중간(mid)보다 작은 경우에는 범위의 끝(right)을 중간-1(mid -1)값으로 설정하고,
  2. 탐색 값이 중간(mid)보다 큰 경우에는 범위의 처음(left)을 중간+1(mid+1)값으로 설정한다.

left  right 를 좁혀가며 최종적으로 탐색 값을 찾는다.

코드

def solution(n, times):
    answer = 0
    # right는 가장 비효율적으로 심사했을 때 걸리는 시간
    # 가장 긴 심사시간이 소요되는 심사관에게 n 명 모두 심사받는 경우이다.
    left, right = 1, max(times) * n
    while left <= right:
        mid = (left+ right) // 2
        people = 0
        for time in times:
            # people 은 모든 심사관들이 mid분 동안 심사한 사람의 수
            people += mid // time
            # 모든 심사관을 거치지 않아도 mid분 동안 n명 이상의 심사를 할 수 있다면 반복문을 나간다.
            if people >= n:
                break
        
        # 심사한 사람의 수가 심사 받아야할 사람의 수(n)보다 많거나 같은 경우
        if people >= n:
            answer = mid
            right = mid - 1
        # 심사한 사람의 수가 심사 받아야할 사람의 수(n)보다 적은 경우
        elif people < n:
            left = mid + 1
            
    return answer

이분 탐색(이진 탐색)으로 알고리즘을 푸는 것이 처음이라서 블로그들의 설명을 요리조리 보면서 이해했다 ㅠㅠ 그래서 주석도 많다

이분 탐색을 할 때는 ‘이분 탐색의 범위는 무엇으로 할지’  ‘이분 탐색의 기준을 무엇으로 할지’ 을 잡아야한다.

  • 범위 : 심사를 하는데 총 걸리는 시간으로, 1분 부터 가장 비효율적으로 심사를 받았을 때 걸리는 시간(분)으로 하였다.
  • mid : 모든 심사관들에게 주어진 시간이다. 따라서 people 은 모든 심사관들이 mid분 동안 심사한 사람의 수가 된다.
  • 기준 : mid 동안 심사한 사람의 수(people)가
    1. 심사 받아야할 사람의 수(n)보다 많거나 같을 경우에는 시간이 충분했던 것이므로 주어진 시간을 줄이고 ( right = mid - 1 -> right 를 줄이면 left와 right의 중간 값인 mid 도 줄어드니까 주어진 시간이 줄어든다.)
    2. 심사 받아야할 사람의 수(n)보다 적은 경우에는 시간이 부족했던 것이므로 주어진 시간을 늘린다. (left = mid + 1)

이분 탐색은 범위와 기준을 잡는 것이 핵심인 것 같다!

Comments