정렬된 배열에서 특정 값을 찾으려고 할 때 빠르게 찾을 수 있다
O(log n)
재귀함수 or 반복문으로 구현 가능하고, 성능 차이도 거의 없다.
하지만 보통 다들 반복문으로 구현하는 듯!
//크기가 size인 arr 배열에서 target 값의 위치 찾기
int search(int *arr, int size, int target){
int left, right, mid;
left = 0;
right = size - 1;
while(left <= right) {
mid = (left + right) / 2;
if(arr[mid] > target) {
right = mid - 1;
} else if(arr[mid] < target) {
left = mid + 1;
} else { //arr[mid] == target
return mid; //return left, return right도 ok
}
}
}
target 이상인 값이 처음 나오는 위치(인덱스) 찾기
int lower_bound(int *arr, int target, int size) {
int left, right, mid;
left = 0;
right = size-1;
while(left<right) { //left<=right 로 하면, l=r=m이고 arr[m]>=target일때 무한반복 걸림
mid = (left + right) / 2;
if(arr[mid] >= target) {
right = mid;
} else { //arr[mid] < target
left = mid + 1;
}
}
return left; //return mid; x //return right; o //엥 셋다 되지 않나?
}
#include <algorithm>
//시작~끝에서 target 이상인 값이 처음 나오는 위치를 반환
lower_bound(배열의 시작, 배열의 끝, target);
//사용
int a = lower_bound(arr, arr+6, 3);
int b = lower_bound(v.begin(), v.end(), 2);
target 보다 큰 값이 처음 나오는 위치(인덱스) 찾기
int upper_bound(int *arr, int target, int size) {
int left, right, mid;
left = 0;
right = size - 1;
while(left<right) {
mid = (left + right) / 2;
if(arr[mid] <= target) {
left = mid + 1;
} else { //arr[mid] > target
right = mid;
}
}
return left; //return right; o
}
#include <algorithm>
//시작~끝에서 target보다 큰 값이 처음 나오는 위치를 반환
upper_bound(배열의 시작, 배열의 끝, target);
//사용
int a = upeer_bound(arr, arr+6, 3);
int b = upper_bound(v.begin(), v.end(), 2);
이분탐색을 이용하여, 최적화 문제를 결정 문제로 바꾸어 해결
3개의 기계에 8개의 작업을 적절히 분배하여
모든 작업을 최대한 빠르게 끝내고자 한다.
그런데, 각 기계들이 하나의 작업을 처리하는 시간이 다른데,
첫번째 기계는 한 개의 작업을 처리하는데 2시간이 걸리고,
두번째 기계는 3시간, 세번째 기계는 7시간이 걸린다.
그렇다면, 모든 작업을 완료하는데 드는 시간의 최솟값은?
모든 작업을 완료하는데 드는 시간이 x라 할 때,
각 기계가 x시간만에 완료하는 작업 수 = x/2, x/3, x/7
세 기계가 x시간동안 완료하는 작업 수 = x/2 + x/3 + x/7
x/2 + x/3 + x/7 >= 8 을 만족하는 최소 x를 구하면 된다.
모든 작업을 완료하는데 드는 시간을 오름차순 배열로 둔게
arr = {7, 8, 9, 10, 11, 12, 13, 14, 15} 라 하면
7 = left, 15 = right로 둬서 arr[mid] 값이 저 조건을 만족하는지 체크!
true(조건 만족) 면, right = mid
false(조건 불만족) 면, left = mid + 1
right = left = mid
일 때 이분 탐색이 중단되고 x = 9
3020 개똥벌레 : lower_bound
2470 두 용액 : 단순히 배열에서 하나의 값을 찾는게 아닌, left와 right의 적당한 합을 조건으로 left, right를 찾아나감(left, right가 답이 됨)