오늘의 학습 키워드
이분 탐색(이진 탐색)이란?
- 정렬되어 있는 리스트에서 탐색 범위를 타노스처럼 절반씩 좁혀가며 데이터를 탐색하는 방법이다.
- 탐색 기법중 하나로, 탐색하고 싶은 범위를 두 부분으로 분할해서 찾는 방법이다.
- 두 부분으로 계속 분할해서 조건에 맞는지 찾아가기 때문에, 시간 복잡도가 O(log n)으로 매우 빠른편
- 무조건 정렬되어 있는 상태에서 이분 탐색을 해야 한다!
https://school.programmers.co.kr/learn/courses/30/lessons/43238
n명이 입국심사를 위해 줄을 서서 기다리고 있습니다. 각 입국심사대에 있는 심사관마다 심사하는데 걸리는 시간은 다릅니다.
처음에 모든 심사대는 비어있습니다. 한 심사대에서는 동시에 한 명만 심사를 할 수 있습니다. 가장 앞에 서 있는 사람은 비어 있는 심사대로 가서 심사를 받을 수 있습니다. 하지만 더 빨리 끝나는 심사대가 있으면 기다렸다가 그곳으로 가서 심사를 받을 수도 있습니다.
모든 사람이 심사를 받는데 걸리는 시간을 최소로 하고 싶습니다.
입국심사를 기다리는 사람 수 n, 각 심사관이 한 명을 심사하는데 걸리는 시간이 담긴 배열 times가 매개변수로 주어질 때, 모든 사람이 심사를 받는데 걸리는 시간의 최솟값을 return 하도록 solution 함수를 작성해주세요.
입국심사를 기다리는 사람은 1명 이상 1,000,000,000명 이하입니다.
각 심사관이 한 명을 심사하는데 걸리는 시간은 1분 이상 1,000,000,000분 이하입니다.
심사관은 1명 이상 100,000명 이하입니다.
n | times | return |
---|---|---|
6 | [7, 10] | 28 |
입국 심사 참 힘들게 생각한다; 문제 만들기도 힘들겠다
위 입출력 예시에 따르면 결론적으로
7분에 1명 -> 10분에 2명 -> 17분에 3명 -> 20분에 4명 -> 21분에 5명 -> 28분에 6명
그래서 28분이라는 값이 결과로 나오는 것이다.
그래서 이걸 왜 이분 탐색으로 푸냐?
1. 이분 탐색 범위 정하기
def solution(n, times):
answer = 0
left = 1
right = max(times) * n
2. 이분 탐색을 통해 심사 가능한 인원 수 계산
while left <= right:
mid = (left+ right) // 2
people = 0
for time in times:
people += mid // time
if people >= n:
break
while left <= right:
:
mid = (left + start) // 2
:
people = 0
for time in times:
people += mid // time
if people >= n:
break
for time in times:
: 3. 탐색 범위 조정:
if people >= n:
answer = mid
right = mid - 1
elif people < n:
left = mid + 1
return answer
if people >= n:
:elif people < n:
:첫 번째 반복 (탐색 범위: [1, 60])
중간값 계산: mid = (1 + 60) // 2 = 30
mid = 30일 때 각 심사관이 심사할 수 있는 사람 수를 계산:
7분 소요되는 심사관: 30 // 7 = 4명
10분 소요되는 심사관: 30 // 10 = 3명
총 people = 4 + 3 = 7
조건 확인:
people (7)이 n (6)보다 크므로 answer = 30, right = 29
두 번째 반복 (탐색 범위: [1, 29])
중간값 계산: mid = (1 + 29) // 2 = 15
mid = 15일 때 각 심사관이 심사할 수 있는 사람 수를 계산:
7분 소요되는 심사관: 15 // 7 = 2명
10분 소요되는 심사관: 15 // 10 = 1명
총 people = 2 + 1 = 3
조건 확인:
people (3)이 n (6)보다 작으므로 left = 16
.
.
.
다섯 번째 반복 (탐색 범위: [27, 29])
중간값 계산: mid = (27 + 29) // 2 = 28
mid = 28일 때 각 심사관이 심사할 수 있는 사람 수를 계산:
7분 소요되는 심사관: 28 // 7 = 4명
10분 소요되는 심사관: 28 // 10 = 2명
총 people = 4 + 2 = 6
조건 확인:
people (6)이 n (6)과 같으므로 answer = 28, right = 27
여섯 번째 반복 (탐색 범위: [27, 29])
중간값 계산: mid = (27 + 27) // 2 = 27
mid = 27일 때 각 심사관이 심사할 수 있는 사람 수를 계산:
7분 소요되는 심사관: 27 // 7 = 3명
10분 소요되는 심사관: 27 // 10 = 2명
총 people = 3 + 2 = 5
조건 확인:
people (5)이 n (6)보다 작으므로 left = 28
탐색 종료
left=28이 right=27보다 크므로 반복문 종료.
최종 answer 값은 28 -> 모든 사람이 심사를 받는 데 걸리는 최소 시간은 28분.
def solution(n, times):
answer = 0
left = 1
right = max(times) * n
while left <= right:
mid = (left+ right) // 2
people = 0
for time in times:
people += mid // time
if people >= n:
break
if people >= n:
answer = mid
right = mid - 1
elif people < n:
left = mid + 1
return answer
🔥 세 번째 같은 이분 탐색을 푸는 문제.. 근데 아직도 적용을 잘 못하겠다,, 문제는 이해했지만 최대값을 구하는 생각, times 배열을 for문으로 돌리는 기초 지식이 부족한 것 같다.
🔥 문제를 계속 풀어봐야 이론뿐 아니라 문제를 푸는 실력이 증진할 것 같다. 하루에 1문제 너무 적나,,일단 꾸준히 해보자!