컴퓨터기본/알고리즘

10. Binary Search(이진 탐색)

차가운오미자 2021. 9. 24. 14:17

 

이진 탐색은 범위를 반으로 나눠가며 찾는 것이다.

선형 탐색보다 훨씬 빠르게 타겟을 찾을 수 있다. 

 

시간 복잡도는 NlogN이다 

 

주의할 점은, 이진 탐색에서 m의 왼쪽에 m보다 작은 요소가, 오른쪽에 m보다 큰 요소가 있는 걸 보장하기 위해, 이진 탐색 전에 배열은 반드시 정렬되어 있어야 한다. 

 

예를 들어서, 9개의 요소를 가진 배열 arr가 있다고 가정하자.

1 2 3 4 5 6 7 8 9

이렇게 있을 때, 3을 찾는다고 하자.

 

일단 전체 arr[0] ~arr[8] 중 중간 요소가 3인지 확인한다.

타겟은 3보다 5가 크므로 5보다 아래에 있다는 소리이다.

 

그럼 다시 arr[0] ~ arr[3] 을 찾아본다.

중간((0+3)/2)은 arr[1] == 2 이다. 

타겟 보다 작으므로 오른쪽에 있다는 소리다.

 

그럼 다시 arr[2] ~ arr[3] 을 찾아본다

중간((2+3)/2 = 2) 인 arr[2]을 보니 3이다. 찾았다!

 

이렇게 탐색 범위를 반으로 쪼개가면서 찾는 것이 이진 탐색이다. 

 

간단하게 코드로 표현하면 다음과 같다

int arr[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

int binarySearch(int s, int e, int target){
    int m;
    while(s<=e){
        m = (s+e)/2;
        if(arr[m] == target) return m+1;
        if(arr[m]>target) e=m-1;
        else s = m+1;
    }
    if(s>e) return 0;
}

 

만약 배열에 중복되는 값이 있다면, 이 중에 가장 후자, 전자를 뽑아낼 수도 있다.

UpperBound Binary Search, LowerBound Binary Search 등으로 부르는데, C++에는 vector에 lower_bound(), upper_bound() 등의 이미 정의된 라이브러리 함수를 사용할 수 있다.

 

C를 통해 upperbound, lowerbound search를 구현해보면 다음과 같다. 

 

Upper Bound Binary Search

// upper_bound binary search
int BinarySearchUpper(int s, int e, int d){
    int m, sol = -1;
    while(s<=e){
        m = (s+e)/2;
        if(narr[m] == d){
            sol = m; // 답의 후보
            s = m+1; // 오른쪽으로 가봄
        }else if(narr[m] > d){
            e = m-1; // 왼쪽을 탐색한다
        }else{
            s = m+1;	// 오른쪽을 탐색한다
        }
    }
    return sol;
}

Lower Bound Binary Search

// lower_bound binary search
int BinarySearchLower(int s, int e, int d){
    int m, sol = -1;
    while(s<=e){
        m = (s+e)/2;
        if(narr[m] == d){
            sol = m; // 답의 후보
            e = m-1; // 왼쪽으로 가봄
            //return m;
        }else if(narr[m] > d){
            e = m-1;
        }else{
            s = m+1;
        }
    }
    return sol;
}

 

기본 이진 탐색과 다른 점은, 타겟을 찾았어도, 리턴하지 않고 왼쪽, 오른쪽으로 탐색을 계속한다는 것이다. 

'컴퓨터기본 > 알고리즘' 카테고리의 다른 글

9. Flood Fill  (0) 2021.09.17
8. Dynamic Programming  (0) 2021.07.06
7. 너비 우선 탐색(BFS), 깊이 우선 탐색(DFS)  (0) 2021.06.14
6. 스택 (Stack), 큐 (Queue)  (0) 2021.06.14
5. 계수 정렬 (Counting Sort)  (0) 2021.06.14