✅ 이진 탐색 자료구조
✓ 이진 탐색 트리
- '왼쪽 자식 노드 < 부모 노드 < 오른쪽 자식 노드'을 성립한다
- 부모 노드부터 탐색한다

(+) 빠르게 입력받기
- 이진 탐색은 입력 데이터가 많거나 탐색 범위가 매우 넓다 -> input()대신 readline()함수를 사용하여 시간 초과를 예방하자
import sys
input_data = sys.stdin.readline().rstrip()
✅ 이진 탐색 구현
- 정렬된 데이터에 한해 사용할 수 있다.
- 시간복잡도: O(log N)
✓ 이진 탐색 소스코드: 재귀적 구현
def binary_search(array, target, start, end);
if start > end:
return None
mid = (start+end)//2
if array[mid] == target:
return mid
elif array[mid] > target:
return binary_search(array, target, start, mid-1)
else:
return binary_search(array, target, mid+1, end)
n, target = list(map(int, input().split()))
array = list(map(int, input().split()))
result = binary_search(array, target, 0,n-1)
if result == None:
print("원소가 존재하지 않습니다.")
else:
print(result+1)
✓ 이진 탐색 소스코드: 반복문 구현
def binary_search(array, target, start, end):
while start <= end:
mid = (start+end)//2
if array[mid] == target:
return mid
elif array[mid] > target:
end = mid - 1
else:
start = mid + 1
return None
✓ 파이썬 이진 탐색 라이브러리
- bisect

- 값이 특정 범위에 속하는 데이터 개수 구하기
from bisect import bisect_left, bisect_right
def count_by_range(a, left_value, right_value):
right_index = bisect_right(a, right_value)
left_index = bisect_left(a, left_value)
return right_index - left_index
a = [ 1,2,3,3,3,3,4,4,8,9]
print(count_by_range(a, 4,4))
print(count_by_range(a, -1, 3))
✅ 이진 탐색 문제 풀이
✓ 파라메트릭 서치(Parametric Search)
- 최적화 문제를 결정 문제('예' 또는 '아니오')로 바꾸어 해결하는 것
예시: 특정한 조건을 만족하는 가장 알맞는 값을 빠르게 찾는 최적화 문제
- 일반적으로 파라메트릭 서치는 이진 탐색으로 해결한다
1. 떡볶이 떡 만들기
- 문제 해결 아이디어
- 높이(H)가 높을수록 떡은 조금 잘린다. 높이가 낮을수록 떡이 많이 잘린다
- 높이가 10억 이하의 양의 정수이다(탐색 범위 매우 큼) -> 순차 정렬은 시간초과 예상. 이진 탐색으로 풀이한다.
- '현재 높이로 자르면 조건에 만족하는가?' 확인 후, 조건에 따라서 범위를 좁혀간다.
- 중간점 값을 시간이 지날수록 '최적화된 값'이 된다. 필요한 떡의 크기보다 크거나 같을 때마다 중간점 값을 기록한다.
n, m = list(map(int, input().split('')))
array = list(map(int, input().split()))
start = 0
end = max(array)
result = 0
while(start<=end):
total = 0
mid = (start+end)//2
for x in array:
if x > mid:
total += x - mid
if total < m:
end = mid - 1
else:
result = mid
start = mid + 1
print(result)
2. 부품 찾기
- 문제 해결 아이디어
- 특정 데이터가 존재하는지 확인하는 문제
- 이진 탐색, 계수 정렬, 집합 자료형(set()) 세 가지 방법으로 해결 가능
(1) 이진 탐색으로 구현


(2) 계수 정렬로 구현
- 모든 원소의 번호를 포함할 수 있는 크기의 리스트를 만든 뒤, 리스트의 인덱스에 직접 접근하여 특정 인덱스에 부품이 있는지 확인
n = int(input())
array = [0] * 1000001
for i in input().split():
array[int(i)] = 1
m = int(input())
x = list(map(int, input(),split()))
for i in x:
if array[i] == 1:
print('yes', end=' ')
else:
print('no', end=' ')
(3) 집합 자료형 이용
- set()함수는 집합 자료형을 초기화할 때 사용한다. 데이터 포함 여부 확인 시 속도가 매우 빠르다는 걸 기억하기.
n = int(input())
array = set(map(int, input().split()))
m = int(input())
x = list(map(int, input(),split()))
for i in x:
if i in array:
print('yes', end=' ')
else:
print('no', end=' ')
✓ 특정 수의 개수 구하기
- 문제 해결 아이디어
- 데이터가 정렬되어 있으므로 이진 탐색 사용
- 특정 값이 등장하는 첫 번째 위치, 마지막 위치의 차를 구한다
- bisect 라이브러리를 활용한다
from bisect import bisect_right, bisect_left
def count_by_range(array, left_value, right_value):
right_index = bisect_right(array, right_value)
left_index - bisect+left(array, left_value)
return right_index - left_index
n,x = map(int, input().split())
array = list(map(int, input().split()))
count = count_by_range(array, x,x)
if count==0:
print(-1)
else:
print(count)