정렬되어 있는 리스트에서 탐색 범위를 절반씩 좁혀가며 데이터를 탐색하는 방법
(이진 탐색은 시작점, 끝점, 중간점을 이용하여 탐색 범위를 설정한다)
다른 탐색으로는 순차탐색이 있고 순차탐색은 데이터를 찾기 위해 앞에서부터 데이터를 하나씩 확인한다.
def binary_search(array, target, start, end):
n, target = list(map(int, input().split()))
array = list(map(int, input().split()))
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
result = binary_search(array, target, 0, n - 1)
if result == None:
print("원소가 존재하지 않습니다")
else:
print(result + 1)
from bisect import bisect_left, bisect_right
def count_by_range(a, l_v, r_v):
r_i = bisect_right(a, r_v)
l_i = bisect_left(a, l_v)
return r_i - l_i
a = [1,2,3,3,3,3,4,4,8,9]
print(count_by_range(a, 4, 4)) # 2
print(count_by_range(a, -1, 3)) # 6
이진 탐색 예제 1 <떡볶이 떡 만들기> (파라메트릭 서치)
m, n = 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
// 현재 떡의 길이 x
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 <정렬된 배열에서 특정 수의 개수 구하기>
from bisect import bisect_left, bisect_right
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()) # 데이터의 개수 N, 찾고자하는 값 X 입력받기
array = list(map(int, input().split()) # 전체데이터 입력받기
# 값이 [x, x] 범위에 있는 데이터의 개수 계산
count = count_by_range(array, x, x)
if count == 0:
print(-1)
else:
print(count)