Lower bound와 Upper bound는 이진 탐색의 변형으로, 정렬된 배열에서 특정값을 효율적으로 찾는데 사용된다.
-> 즉, 경계값을 찾는 알고리즘이다. 이진탐색을 기반으로 하기 때문에 정렬되어 있어야 한다.
이진탐색을 기반으로 하기 때문에, 두 알고리즘의 시간 복잡도는 O(logN)이다.
정의 : 주어진 값 이상인 첫번째 원소의 위치를 반환.
정의 : 주어진 값보다 큰 첫번째 원소의 위치를 반환
Lower bound는 특정 값의 시작위치를 찾는 알고리즘이다.
초기에 left는 배열의 시작위치로 right는 배열의 길이로 세팅한다.
1. 배열의 중간값(mid)를 가져온다.
2. 중간 값과 검색 값을 비교한다.
arr배열에서 k=3의 lower bound를 찾는 과정
arr배열에서 k값의 lower bound를 찾는 코드
def lower_bound(arr, left, right, k):
while left < right:
mid = (left + right)//2
if arr[mid] < k:
left = mid + 1
else:
right = mid
return right
정확히 일치하는 값이 없더라도, 찾고자 하는 값(k)이상인 첫번째 원소의 위치를 반환한다.
Upper Bound는 특정 K값보다 처음으로 큰 값의 위치를 찾는 알고리즘이다.
Upper Bound의 동작 방식...
초기에 left는 배열의 시작위치, right는 배열의 길이로 세팅한다.
1. 배열의 중간값(mid)를 가져온다.
2. 중간 값과 검색값을 비교한다.
arr배열에서 k=3의 upper bound를 찾는 과정
arr배열에서 k값의 upper bound를 찾는 코드
def upper_bound(arr, left, right, k):
while left < right:
mid = (left + right)//2
if arr[mid] <= k:
left = mid + 1
else:
right = mid
return right
정확히 일치하는 값이 없더라도, 그 값보다 큰 첫번째 원소의 위치를 반환한다.
import bisect
arr = [1, 2, 3, 3, 3, 4, 5]
x = 3
# Lower bound
left_index = bisect.bisect_left(arr, x)
print(f"Lower bound of {x}: {left_index}") # 출력: 2
# Upper bound
right_index = bisect.bisect_right(arr, x)
print(f"Upper bound of {x}: {right_index}") # 출력: 5
# 특정 값의 개수 구하기
count = right_index - left_index
print(f"Count of {x}: {count}") # 출력: 3
bisect.bisect_left는 lower bound 역할을 한다.
위 예시에서 배열 arr에서 x의 lower bound를 찾음
bisect.bisect_right는 upper bound와 동일한 역할을 한다.
위 예시에서 정렬된 리스트 arr에서 x를 삽입할 수 있는 가장 오른쪽 인덱스 반환