이분 탐색은 정렬된 배열에서 특정 값을 찾거나 범위를 구할 때 사용되는 효율적인 알고리즘. 이분 탐색은 배열을 반으로 나누면서 탐색 범위를 좁혀 나가며 원하는 값을 찾는다.

이분 탐색은 다음과 같은 단계로 이루어집니다:
1. 배열의 중간 값을 찾는다.
2. 중간 값이 찾고자 하는 값과 같으면 탐색을 종료.
3. 중간 값이 찾고자 하는 값보다 크면 중간 값의 왼쪽 부분 배열에서 탐색
4. 중간 값이 찾고자 하는 값보다 작으면 중간 값의 오른쪽 부분 배열에서 탐색
5. 찾고자 하는 값을 찾거나 탐색 범위가 없을 때까지 이 과정을 반복
이분 탐색의 시간 복잡도는 O(log n)
절반씩 줄여나간다고 생각하면 된다.
public int upperBound(int[] array, int target) {
int left = 0;
int right = array.length;
while (left < right) {
int mid = left + (right - left) / 2;
if (array[mid] <= target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
public int lowerBound(int[] array, int target) {
int left = 0;
int right = array.length;
while (left < right) {
int mid = left + (right - left) / 2;
if (array[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
매우 중요
최적화 문제(문제의 상황을 만족하는 특정 변수의 최솟값, 최댓값을 구하는 문제)를 결정 문제(decision problem)로 바꾸어 푸는 것
문제 예시
여러 개의 짐을 싣고 있는 배가 있다. 각 짐의 무게가 주어졌을 때, 배가 견딜 수 있는 최대 무게를 넘지 않으면서 배에 최대한 많은 짐을 싣고 싶다. 배의 최대 무게가 maxWeight로 주어졌을 때, 배에 실을 수 있는 최대 짐의 무게를 구시오.
public class ParametricSearch {
// 주어진 무게로 배에 짐을 실을 수 있는지 확인하는 함수
public static boolean canLoad(int[] weights, int maxWeight, int limit) {
int currentWeight = 0;
for (int weight : weights) {
if (currentWeight + weight > limit) {
return false;
}
currentWeight += weight;
}
return currentWeight <= maxWeight;
}
// 파라메트릭 서치 함수
public static int parametricSearch(int[] weights, int maxWeight) {
int left = 0;
int right = maxWeight;
int result = 0;
while (left <= right) {
int mid = left + (right - left) / 2;
if (canLoad(weights, maxWeight, mid)) {
result = mid; // 가능한 최대 무게 갱신
left = mid + 1; // 더 큰 무게를 탐색
} else {
right = mid - 1; // 더 작은 무게를 탐색
}
}
return result;
}
public static void main(String[] args) {
int[] weights = {10, 20, 30, 40, 50};
int maxWeight = 100;
System.out.println("배에 실을 수 있는 최대 무게: " + parametricSearch(weights, maxWeight));
}
}