-
[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; } }
채점결과
'Programming > Algorithm' 카테고리의 다른 글
[Java] 백준 11728 배열 합치기 (0) 2021.03.05 [Java] 프로그래머스 징검다리 (0) 2021.03.05 [Java] 백준 10815 숫자 카드 (0) 2021.03.03 [Java] 백준 2110 공유기 설치 (0) 2021.03.03 [Java] 백준 2805 나무 자르기 (0) 2021.03.03 댓글