동일한 O(logn)의 시간 복잡도가 요구되어도 분모의 값이 삼진은 3이고 이진은 2이기 때문에 더 효과적인 것인가?
하지만 예상과 다르기 실제로는
이진 탐색이 훨씬 더 선호됩니다
. 그 이유는 최악의 경우, 삼진 탐색 방식은 비교를 더 많이 해야하기 때문입니다.
2-1. 삼진 탐색 구현 코드
// 재귀 호출 사용
public static int recursiveSearch(int[] arr, int x, int start, int end){
if(start > end)
return -1;
int mid1 = start + (end - start) / 3;
int mid2 = end - (end - start) / 3;
if(arr[mid1] == x){
return mid1;
}
if(arr[mid2] == x){
return mid2;
}
if(x < arr[mid1]){
return recursiveSearch(arr, x, 0, mid1-1);
} else if(x > arr[mid2]){
return recursiveSearch(arr, x, mid2+1, end);
} else {
return recursiveSearch(arr, x, mid1+1, mid2-1);
}
}
3. 지수 탐색(Exponential Search)
이것도 크게 다른 점은 없지만 찾는 방식이 조금 다릅니다.
1, 2, 4, 8, ... 이런 식으로 탐색 index 값을 지수 형태로 높여가면서 구간을 탐색하는 방식입니다. 다른 탐색과 마찬가지로 이런 과정을 통해 탐색을 진행하다가 해당되는 범위를 찾으면 그 안에서 다시 선형 혹은 이진 탐색을 통해 최종 값을 찾는 것입니다.
시간 복잡도는 O(logn)이 되겠습니다.
3-1. 지수 탐색 구현 코드
public static int search(int[] arr, int x){
// 가장 앞의 위치에 있다면 바로 반환, 1부터 시작할 것이기 때문
if(arr[0] == x){
return 0;
}
int i=1;
// index 값이 배열 크기보다 작아야 그 안에서 구간을 찾는다.
// 또한 배열의 값이 더 작은 동안에만 수행하여 구간을 찾는다.
while(i < arr.length && arr[i] <= x){
i = i * 2;
}
// 찾아낸 구간에서 이진 탐색으로 수행
// i값이 전체 배열의 범위를 넘어갈 수 있으니 Math.min으로 설정
return Arrays.binarySearch(arr, i/2, Math.min(i, arr.length-1), x);
}