Binary Search (이진 탐색)
순차 탐색
앞에서부터 하나씩 차례대로 탐색하는 방법
array = [3, 1, 7, 5, 9]
for i in range(len(array)):
if array[i] == 7:
print(i)
리스트를 차례대로 순회하므로 시간 복잡도는 O(N)
이다.
이진 탐색
정렬된 리스트에 대하여 찾으려는 데이터와 중간 지점의 데이터를 비교해나가며 탐색하는 방법
순차 탐색과 달리 정렬이 되어 있어야 사용할 수 있다.
중간이 정확히 안 나누어질 때는 소수점 이하를 버린다.
시간 복잡도는 O(logN)
이다.
구현 - 반복문 (권장)
def binary_search(array, target, start, end):
while start <= end:
middle = (start + end) // 2
if target > array[middle]:
start = middle + 1
elif target < array[middle]:
end = middle - 1
else:
return middle
return None
array = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
target = int(input())
index = binary_search(array, target, 0, len(array) - 1)
print(index) if index != None else print("원소가 존재하지 않습니다.")
구현 - 재귀함수
def binary_search(array, target, start, end):
if start > end:
return None
middle = (start + end) // 2
if target > array[middle]:
return binary_search(array, target, middle + 1, end)
elif target < array[middle]:
return binary_search(array, target, start, middle - 1)
else:
return middle
array = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
target = int(input())
index = binary_search(array, target, 0, len(array) - 1)
print(index) if index != None else print("원소가 존재하지 않습니다.")
이진 탐색을 사용하는 경우
찾아야 할 자료가 여러 개인 경우
총 데이터 수가 N개, 찾아야 할 자료가 M개일 때 순차 탐색을 이용하면 O(M * N)
만큼의 시간이 걸린다. 그러나 이진 탐색을 이용하면 정렬에 O(NlogN)
, 탐색에 O(MlogN)
만큼의 시간이 걸리므로 총 O((M + N)logN)
만큼의 시간이 걸린다. 따라서 M의 값이 커질수록 이진 탐색을 이용한 탐색이 더 효율적이게 된다.
위의 경우 값의 범위가 크지 않은 경우에는 계수 정렬을 이용할 수도 있다.
최적화 문제를 결정 문제로 바꾸는 파라매트릭 서치
문제
파라매트릭 서치
문제정답이 될 수 있는 수의 범위를 정하고 이 범위 내에서 이진 탐색을 수행한다.
원리
자동 정렬이 되어있다는 장점
수의 범위만 정하기 때문.
1부터 100까지 라고 정하면 [1, 2, 3, ... , 99, 100] 이라는 가상의 배열이 있다고 가정
항상 최적의 값에 가까워진다는 점을 이용
사용법
최적에 가까운 유효한 값을 얻을 때마다 반환할 결과값을 갱신한다.
N이 최적값이고 N보다 큰 값을 허용한다면 N보다 큰 유효값을 만날 때마다 갱신
파라매트릭 서치는 타겟값을 찾아도 바로 반환하면 안 된다.
타겟값이 최적값이라는 보장이 없기 때문
Last updated