Programming/JAVA
이분 탐색(Binary Search) 개념과 구현
gayeon_
2024. 9. 17. 14:50
이분 탐색
- 순차적 탐색보다 빠른 방식(시간 복잡도 낮음)
- 정렬된 배열에서 특정 원소를 찾을 때 중간 값을 구함
- 중간 값이 찾는 원소가 아니라면 중간 값이 특정 원소보다 큰지 작은지 판단하여 탐색 범위를 수정
- 이러한 방식으로 탐색 범위를 반씩 줄여 특정 원소를 찾는 방법이 이분 탐색
이분 탐색의 기본 원리
- 배열의 중앙 요소를 선택한다.
- 찾고자 하는 값이 중앙 요소보다 작으면 왼쪽 절반을 탐색하고 크면 오른쪽 절반을 탐색한다.
- 이 과정을 반복하여 값을 찾거나 배열이 비어있을 때까지 진행한다.
이분 탐색 구현
1) 반복적 방법(Iterative Approach)
public class BinarySearch {
// 배열이 정렬되어 있다고 가정
public static int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid; // 값을 찾았을 때의 인덱스 반환
}
if (arr[mid] < target) {
left = mid + 1; // 오른쪽 절반 탐색
} else {
right = mid - 1; // 왼쪽 절반 탐색
}
}
return -1; // 값을 찾지 못했을 때
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int target = 5;
int result = binarySearch(arr, target);
if (result != -1) {
System.out.println("찾은 값의 인덱스: " + result);
} else {
System.out.println("값을 찾을 수 없습니다.");
}
}
}
반복적 방법은 while 루프를 사용하여 이분 탐색을 수행한다.
이 방법은 스택 오버플로우 문제를 피할 수 있어 대규모 데이터에 적합하다.
중앙값 계산: (left + right) / 2 대신 left + (right - left) / 2를 사용해야 오버플로우를 방지할 수 있다. 매우 큰 정수 계산 시 전자를 사용하면 오버플로우가 발생할 수 있다.
동작 원리
초기화: 배열의 시작 인덱스 (left)와 끝 인덱스 (right)를 설정한다.
루프
- 중앙 인덱스 (mid)를 계산한다.
- 중앙 인덱스의 값이 목표값과 같으면 mid를 반환한다.
- 목표값이 중앙값보다 작으면 오른쪽 절반을 버리고 왼쪽 절반으로 탐색을 계속한다.
- 목표값이 중앙값보다 크면 왼쪽 절반을 버리고 오른쪽 절반으로 탐색을 계속한다.
종료: 목표값을 찾으면 해당 인덱스를 반환하고 찾지 못하면 -1을 반환한다.
2) 재귀적 방법 (Recursive Approach)
public class BinarySearch {
// 배열이 정렬되어 있다고 가정
public static int binarySearch(int[] arr, int left, int right, int target) {
if (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid; // 값을 찾았을 때의 인덱스 반환
}
if (arr[mid] < target) {
return binarySearch(arr, mid + 1, right, target); // 오른쪽 절반 탐색
} else {
return binarySearch(arr, left, mid - 1, target); // 왼쪽 절반 탐색
}
}
return -1; // 값을 찾지 못했을 때
}
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int target = 5;
int result = binarySearch(arr, 0, arr.length - 1, target);
if (result != -1) {
System.out.println("찾은 값의 인덱스: " + result);
} else {
System.out.println("값을 찾을 수 없습니다.");
}
}
}
재귀적 방법은 함수가 자기 자신을 호출하여 이분 탐색을 수행한다.
구현이 간결하지만 깊은 재귀 호출이 필요한 경우 스택 오버플로우를 일으킬 수 있다.
동작 원리
배열의 시작 인덱스가 끝 인덱스보다 크면 탐색 범위가 없으므로 -1을 반환한다.
재귀 호출
- 중앙 인덱스 (mid)를 계산한다.
- 중앙 인덱스의 값이 목표값과 같으면 mid를 반환한다.
- 목표값이 중앙값보다 작으면 오른쪽 절반을 버리고 왼쪽 절반을 재귀적으로 탐색한다.
- 목표값이 중앙값보다 크면 왼쪽 절반을 버리고 오른쪽 절반을 재귀적으로 탐색한다.