본문 바로가기

Algorithm

😊 프로그래머스: Lv3. 입국 심사 (Java)

📌 문제

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

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

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

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

📌 제한사항

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

📌 풀이

제한사항을 보면 최대 기다리는 사람은 10억, 1명이 심사하는데 걸리는 시간은 10억분 이하. 단순 구현으로는 시간 초과될 가능성이 매우 높다. 어떻게 접근해야 할지 고민했다. 모든 사람을 심사하는데 걸리는 최대 시간으로 이분 탐색을 해보자.

심사하는데 걸리는 최대 시간 = 1명 심사하는데 걸리는 최대 시간 x 최대 심사관 수
즉, 10억분 x 10만명으로 100조가 나온다... (long 타입은 100조 커버 가능)

min 값을 1, max를 100조로 두고 중간값(mid)을 전체 걸리는 시간(totalTime)으로 가정한다. 이때 모든 심사관이 totalTime 동안 몇명을 심사 할 수 있는지 카운트 한다. 만약에 심사를 기다리는 사람 수(n)보다 크거나 같으면, min과 mid 사이에 최소값이 있다. 만약에 작다면, mid와 max 사이에 최소값이 있다. 이를 이용하면 원하는 결과를 얻을 수 있다.

쉽게 얘기하자면 숫자 맞추기 게임과 같다. 1부터 100까지 숫자중에 홍길동이 생각하는 숫자를 맞춰보자. 1부터 100까지 얘기하다보면 언젠간 나올 것이다. 하지만 비효율적이지 않은가? 내가 제시하는 숫자에 대해서 홍길동은 크거나 작은지만 얘기해준다고 해보자. 그러면 아래와 같이 쉽게 답을 찾을 수 있다.

홍길동이 생각하는 숫자: 70
50 -> 크다. (50보다 크고, 100보다 작다)
75 -> 작다. (50보다 크고, 75보다 작다)
62 -> 크다. (62보다 크고, 75보다 작다)
68 -> 크다. (68보다 크고, 75보다 작다)
71 -> 작다. (68보다 크고, 71보다 작다)
69 -> 크다. (69보다 크고, 71보다 작다) -> 70

입국 심사 문제도 이와 같이 이분 탐색을 이용하여 짧은 코드로 해결할 수 있었다.

📌 코드

public class 입국심사 {

    @Test
    void test() {
        long solution = solution(6, new int[]{7, 10});
        assertThat(solution).isEqualTo(28);
    }

    public long solution(int n, int[] times) {
        long min = 1L;
        long max = 1_000_000_000L * 100_001L;

        while (min <= max) {
            long mid = (min + max) / 2;
            if (isBig(mid, times, n)) max = mid - 1L;
            else min = mid + 1L;
        }
        return min;
    }

    private boolean isBig(long totalTime, int[] times, int n) {
        long count = 0L;
        for (int time : times) {
            count += (totalTime / time);
        }
        return count >= n;
    }
}
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr