이분 탐색
오름차순으로 정렬된 리스트에서 특정한 값의 위치를 찾는 알고리즘
찾고자 하는 값과 중간값을 반복적으로 비교해 탐색 범위를 절반씩 좁혀가며 데이터를 탐색함
변수 3개(high, low, mid) 사용
- 처음 리스트의 중간값을 임의의 값으로 선택 mid = (low + high) / 2
- 그 값과 찾고자 하는 값의 크고 작음을 비교
- 처음 선택한 중앙값이 만약 찾는 값보다 크면(mid > key) 그 값은 새로운 최댓값이 됨 (high = mid - 1)
- 작으면(mid < key) 그 값은 새로운 최솟값이 됨 (low = mid + 1)
- 같으면 (mid == key) 중간값 리턴 후 종료
장점
검색이 반복될 때마다 탐색 범위가 반으로 줄어들어 목표값을 찾을 확률이 두 배가 되므로 속도가 빠름
시간 복잡도: O(log N)
비교 횟수 | 범위 |
0 | n |
1 | n / 2 |
2 | n / 2^2 |
... | ... |
k | n / 2^k |
n / 2^k = 1 이므로 k 값은 log2 n
단점
정렬된 리스트에만 사용 가능
의사코드
재귀호출
BinarySearch(A[0..N-1], value, low, high) {
if (high < low)
return -1 // not found
mid = (low + high) / 2
if (A[mid] > value)
return BinarySearch(A, value, low, mid-1)
else if (A[mid] < value)
return BinarySearch(A, value, mid+1, high)
else
return mid // found
}
반복
binarySearch(A[0..N-1], value) {//k
low = 0
high = N - 1
while (low <= high) {
mid = (low + high) / 2
if (A[mid] > value)
high = mid - 1
else if (A[mid] < value)
low = mid + 1
else
return mid // found k
}
return -1 // not found k
}
반복 구조를 사용하는 것이 재귀 호출을 사용하는 것보다 더 효율적임
자바
public int binarySearch(int[] arr, int target) {
int start = 0;
int end = arr.length - 1;
int mid = 0;
while (start <= end) {
mid = (start + end) / 2;
if (target == arr[mid]) {
return mid;
}else if (arr[mid] < target) {
start = mid + 1;
}else if (target < arr[mid]) {
end = mid - 1;
}
}
throw new NoSuchElementException("can't find target.");
}
출처
- https://ko.wikipedia.org/wiki/%EC%9D%B4%EC%A7%84_%EA%B2%80%EC%83%89_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98
- https://velog.io/@kimdukbae/%EC%9D%B4%EB%B6%84-%ED%83%90%EC%83%89-%EC%9D%B4%EC%A7%84-%ED%83%90%EC%83%89-Binary-Search
- https://minhamina.tistory.com/127
'스터디 > 알고리즘' 카테고리의 다른 글
[알고리즘] 누적합 알고리즘 (Prefix sum algorithm) (0) | 2024.11.05 |
---|
댓글