ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 프로그래머스 입국심사
    Programming/Algorithm 2021. 3. 5. 01:28

     

    문제

    입국심사를 기다리는 사람들과 심사를 맡은 심사관들이 있다. 

    심사를 기다리는 사람 수를 n, 각각의 심사관이 1명을 심사하는 데 걸리는 시간이 담긴 배열 times가 주어졋을 때

    n명 모두 심사를 받기 위해서 걸리는 최소 시간을 리턴하는 문제이다.

     

    - 1 <= n <= 10억(명)

    - 1분 <= times 요소 <= 10억(분)

    - 1 <= times 배열 길이 <= 10만(명)

     

    1) 브루트 포스 => 정확도 33.3% 시간초과

    처음엔 단순하게 주어진 논리대로 구현했다.

    - while문을 돌면서 시간을 1씩 증가시킨다.

    - 'int time(심사하는 데 걸리는 시간)', 'int inspected(현재 심사중인 사람 소요시간)' 속성을 담는 Examiner(검사관)클래스를 두었다.

    - ArrayList<Examiner> Immigration 을 생성하고, 시간이 1 지날 때마다 inspected를 1씩 증가한다.

    - 만약 inspected가 time과 같아지면 complete(완료된 사람)을 하나 증가시키고 해당 인스턴스의 inspected변수를 0으로 초기화한다.

    - n에서 완료된 사람을 뺄셈연산하고 n이 0이되는 시간을 리턴한다.

     

    하지만 10억명의 사람을 검사하고, 심사관이 10만명으로 주어진 경우에

    시간이 1 증가할 때마다 ArrayList를 10만번씩 선형탐색하고, 10억명의 complete가 나올 때까지 반복해야 하기 때문에 효율적이지 못하다.

     

     

    2) 이진탐색 => 정확도 100%

    문제의 요구사항은 단순히 '최소시간'을 리턴하는 것이다.

    따라서 탐색 대상을 '모든 사람이 검사 받는 시간'으로 두고 이진탐색으로 시간을 추정해나갈 수 있다.

    - 최소 검사시간 : 1

    - 최대 검사시간 : 검사받는 사람 수 * 제일 적은 검사관의 시간

    - 시간을 추정해서 해당 시간동안 n명을 검사할 수 있는지를 체크하면 된다. 

    - (ex) n = 6, 20 min ? times = {7,10} : 20 / 7 + 20 / 10 = 2 + 2 => 4명 검사 가능 (조건만족x)

    - (ex) n = 6 30 min ? times = {7,10} : 30 / 7 + 30 / 10 = 4 + 3 => 7명 검사 가능 (조건만족o)

     

     

    코드

    import java.util.ArrayList;
    import java.util.Arrays;
    
    public class Main {
    
        public static void main(String[] args) {
            int n = 6;
            int[] times = {7, 10};
    //        System.out.println(solution1(n, times)); // 1) 브루트포스 : 시간초과
            System.out.println(solution2(n, times)); // 2) 이진탐색 : 성공
        }
    
    
    // solution1 
        static class Examiner {
            int time;
            int inspected;
    
            public Examiner(int time) {
                this.time = time;
                this.inspected = 0;
            }
        }
    
        static int setInspectedTime(ArrayList<Examiner> immigration) {
            int complete = 0;
    
            for (int i = 0; i < immigration.size(); i++) {
                Examiner e = immigration.get(i);
                e.inspected++;
                if (e.time == e.inspected) {
                    complete++;
                    e.inspected = 0;
                }
            }
    
            return complete;
        }
    
        static long solution1(int n, int[] times) {
            long current_time = 0;
    
            Arrays.sort(times);
            ArrayList<Examiner> immigration = new ArrayList<>();
            for (int i = 0; i < times.length; i++) {
                immigration.add(new Examiner(times[i]));
            }
    
            int wait = n;
            while (wait > 0) { // 등호?
                int complete = setInspectedTime(immigration);
                wait -= complete;
                current_time++;
            }
    
            return current_time;
        } // solution1 end
    
        // 2) 이진탐색
        static long solution2(int n, int[] times) {
            Arrays.sort(times);
            long shortest = 1, longest = (long) n * times[0]; 
    
            long result = Long.MAX_VALUE;
            while (shortest <= longest) {
                long mid = (shortest + longest) / 2;
                if (isPossible(mid, times, n)) {
                    result = Math.min(mid, result);
                    longest = mid - 1;
                } else {
                    shortest = mid + 1;
                }
            }
    
            return result;
        }
    
        // 추정한 시간(time) 내에 사람 n명을 검사할 수 있는지 확인
        static boolean isPossible(long time, int[] times, int n) {
            long cnt = 0;
            for (int i = 0; i < times.length; i++) {
                cnt += time / times[i];
            }
            return cnt >= n;
        }
    }
    

     

     

    채점결과

     

    댓글

Designed by black7375.