|
| 1 | +# 보현 4주차 이분탐색 |
| 2 | + |
| 3 | +## 01. 입국심사 |
| 4 | + |
| 5 | +더 빨리 끝나는 곳이 있는지 체크하는 과정이 필요함 |
| 6 | +-> 빈 심사대의 소요시간 vs 기다리는 시간 + 심사하는 데 걸리는 시간 |
| 7 | + |
| 8 | +예) 7분 기다림 + 7분 소요 > 10분 소요 -> 이 경우 10분 소요되는 심사대로 갈 것 |
| 9 | + |
| 10 | +이를 구현할 수 있는 논리구조는 다음과 같다. |
| 11 | + |
| 12 | +1. 특정 심사대에 있는 사람 수 리스트를 생성, 줄 설 때마다 사람 원소 추가 |
| 13 | +2. 원소별로 시간 계산하기 (시간 비교) |
| 14 | + |
| 15 | +였는데...이를 구현하는 데 어려움을 겪었다. |
| 16 | + |
| 17 | +- 문제 1 : 객체처럼 써보려고 했는데 실패함. |
| 18 | +- 문제 2 : 각각의 리스트를 만드려고 했는데 몇 개의 times가 들어올 지 모르기 때문에 변수 선언이 어려움(너무 많아짐) |
| 19 | +- 문제 3 : dictionary를 써볼까 했지만... key-value 각각 할당하는게 좀 귀찮음 |
| 20 | + |
| 21 | +그래서 GPT의 도움을 빌렸다! |
| 22 | +주제에 맞게 이분탐색을 활용했어야 하는데 그러지 못햇다.. |
| 23 | + |
| 24 | +```JavaScript |
| 25 | +function solution(n, times) { |
| 26 | + // 최소 시간 |
| 27 | + let left = 1; |
| 28 | + // 최대 시간: 가장 느린 심사관이 모두 처리하는 경우 |
| 29 | + let right = Math.max(...times) * n; |
| 30 | + |
| 31 | + while (left < right) { |
| 32 | + const mid = Math.floor((left + right) / 2); |
| 33 | + // 중간 시간 내에 처리할 수 있는 사람의 수 |
| 34 | + const peopleProcessed = times.reduce((sum, time) => sum + Math.floor(mid / time), 0); |
| 35 | + |
| 36 | + // 처리할 수 있는 사람의 수가 n보다 크거나 같으면 시간 줄이기 |
| 37 | + if (peopleProcessed >= n) { |
| 38 | + right = mid; |
| 39 | + } else { |
| 40 | + left = mid + 1; |
| 41 | + } |
| 42 | + } |
| 43 | + |
| 44 | + return left; |
| 45 | +} |
| 46 | +``` |
| 47 | + |
| 48 | +### 분석 |
| 49 | + |
| 50 | +이분 탐색은 처음부터 하나하나 계산하는 게 아니라 중간 지점(mid)을 사용한다는 점에서 강점을 가진다. |
| 51 | +그렇기 때문에 중간 지점이 있다는 건 -> 최대/최소도 있다는 것. 그 둘의 중간점이 mid 값일 것이다 |
| 52 | + |
| 53 | +위 코드에서 사용한 논리구조다 |
| 54 | + |
| 55 | +- 각 심사대에서 최종 걸리는 최소시간과 최대시간을 구한다 |
| 56 | + - 1. 최소 : 1분(혹은 0분) |
| 57 | + - 2. 최대 : 가장 오래 걸리는 심사대에서 n명 모두 받을 경우 |
| 58 | +- 중간값을 구하여 이 시간 내에 모든 사람들이 심사를 받을 수 있는지 확인한다 |
| 59 | + (이때, 중간값을 구하는 이유는 그냥 처음부터 하면 많으니까... 임의로 설정한 것) |
| 60 | + - 모두 심사가능 : 더 최소 시간이 있는지를 확인하기 위해 최대시간 = mid로 설정 |
| 61 | + - 심사 불가 : 시간이 충분하지 않다는 의미이므로 최소 = mid로 설정 |
| 62 | +- 최대>최소가 아니면 종료 (값을 찾았다는 의미) |
| 63 | + |
| 64 | +### 내가 놓친 부분 |
| 65 | + |
| 66 | +이분탐색이라는 정말 쉬운 계산방법을 생각지 못하고 처음부터 차근차근 하려 한 것! |
| 67 | +_무엇보다 **임의의 값**을 사용했어도 됐었다는 점을 캐치하지 못했다._ |
| 68 | + |
| 69 | +중간값이라고 해서 정확한 값이 아니어도 된다! 최소 시간에 1씩 더한 것처럼... |
| 70 | +아무튼 쉽게 생각해보자 |
| 71 | + |
| 72 | +## 02. 징검다리 |
| 73 | + |
| 74 | +문제 이해가 너무 어려워서 뭔 소린지 한참을 이해해봤는데... |
| 75 | +일단 이해한 바를 정리해서 작성한 논리구조는 다음과 같음 |
| 76 | + |
| 77 | +1. 바위의 위치를 오름차순으로 정렬함 (첫번째 바위-마지막 바위 떨어진 거리를 구하기 위함) |
| 78 | +2. 이분탐색의 방법을 활용하여 start,end를 정하고 mid를 점점 찾아나가기 |
| 79 | + 1. mid값보다 거리가 더 작은 바위가 있다면 제거 (왜냐면 ... 최솟값이니까) |
| 80 | + 2. 제거한 바위가 n개 이상이면 오류 -> mid 1 감소 |
| 81 | + |
| 82 | +```JavaScript |
| 83 | +function solution(distance, rocks, n) { |
| 84 | + rocks.sort((a, b) => a - b); //바위 오름차순 정렬 |
| 85 | + var start = 0, end = distance; |
| 86 | + |
| 87 | + while (start <= end) |
| 88 | + { |
| 89 | + var mid = Math.floor((start + end) / 2); |
| 90 | + |
| 91 | + for (var eachRock of rocks) { |
| 92 | + var count = 0; |
| 93 | + |
| 94 | + if () //여기서 막힘 -> mid값보다 거리가 더 작은 바위 제거 부분을 rocks의 하나하나 판단해야하는지... |
| 95 | + } |
| 96 | + |
| 97 | + } |
| 98 | +} |
| 99 | +``` |
| 100 | + |
| 101 | +```JavaScript |
| 102 | +function solution(distance, rocks, n) { |
| 103 | + rocks.sort((a, b) => a - b); //바위 오름차순 정렬 |
| 104 | + var start = 0, end = distance; |
| 105 | + |
| 106 | + function isPossible(mid) { |
| 107 | + let removeCount = 0; |
| 108 | + let prevPosition = 0; |
| 109 | + |
| 110 | + for (let rock of rocks) { |
| 111 | + if (rock - prevPosition < mid) { |
| 112 | + removeCount++; |
| 113 | + if (removeCount > n) { |
| 114 | + return false; |
| 115 | + } |
| 116 | + } else { |
| 117 | + prevPosition = rock; |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + if (distance - prevPosition < mid) { |
| 122 | + removeCount++; |
| 123 | + if (removeCount > n) { |
| 124 | + return false; |
| 125 | + } |
| 126 | + } |
| 127 | + |
| 128 | + return true; |
| 129 | + } |
| 130 | + |
| 131 | + while (start <= end) { |
| 132 | + let mid = Math.floor((start + end) / 2); |
| 133 | + if (isPossible(mid)) { |
| 134 | + start = mid + 1; |
| 135 | + } else { |
| 136 | + end = mid - 1; |
| 137 | + } |
| 138 | + } |
| 139 | + |
| 140 | + return end; |
| 141 | +} |
| 142 | +``` |
0 commit comments