Menu
Coddy logo textTech

이진 탐색

마지막 업데이트

이진 탐색은 **정렬된** 배열에서 탐색 범위를 반복적으로 절반씩 줄여 목표 값을 찾습니다. 가운데 요소를 목표 값과 비교해서 일치하면 탐색이 끝나고, 그렇지 않으면 목표 값이 있을 수 없는 절반을 버리고 범위를 나머지 절반으로 좁힙니다. 비교할 때마다 남은 요소의 절반이 제거되므로 O(log n) 시간에 동작합니다 — 정렬된 값 100만 개를 탐색해도 비교는 최대 약 20번이면 충분합니다.

위 애니메이션은 lo, mid, hi 포인터를 보여 주고, 비교가 끝날 때마다 제거된 절반을 흐리게 표시합니다. 단 하나의 절대 전제 조건은 배열이 이미 정렬되어 있어야 한다는 것입니다 — 정렬되지 않은 데이터에는 선형 탐색을 쓰거나 먼저 정렬해야 합니다(병합 정렬 참고). 이 절반으로 나누는 아이디어는 이진 탐색 트리의 기반이기도 합니다.

시간 및 공간 복잡도

경우복잡도비고
최선의 경우O(1)첫 번째 비교에서 가운데 요소가 목표 값인 경우.
평균적인 경우O(log n)비교할 때마다 남은 범위가 절반으로 줄어든다.
최악의 경우O(log n)일치 또는 실패가 확정되기 전에 범위가 요소 하나까지 줄어든다.
공간O(1)반복 버전은 lo, hi, mid 인덱스만 유지한다.

단계별 과정

단계무슨 일이 일어나는가
1lo를 정렬된 배열의 첫 번째 인덱스로, hi를 마지막 인덱스로 설정한다.
2가운데 인덱스를 계산한다: mid = (lo + hi) // 2.
3a[mid]가 목표 값과 같으면 mid를 반환한다 — 발견.
4a[mid]가 목표 값보다 **작으면**, 목표 값은 오른쪽 절반에만 있을 수 있다: lo = mid + 1로 설정한다.
5a[mid]가 목표 값보다 **크면**, 왼쪽 절반을 탐색한다: hi = mid - 1로 설정한다.
6lo <= hi인 동안 2단계부터 반복한다. 범위가 비면 목표 값은 배열에 없다.

풀이 예제

[1, 2, 3, 5, 7, 8, 9]에서 5를 탐색하는 경우:

패스범위 (lo..hi)mida[mid]동작
1[1, 2, 3, 5, 7, 8, 9] (0..6)35a[3] = 5 — 인덱스 3에서 목표 값 발견.

실패하는 탐색, 단계별로

같은 배열에서 4를 탐색하면 범위가 어떻게 비는지 볼 수 있습니다:

패스범위 (lo..hi)mida[mid]동작
10..6355 > 4 — 왼쪽 절반 탐색, hi = 2.
20..2122 < 4 — 오른쪽 절반 탐색, lo = 2.
32..2233 < 4lo가 3이 되어 범위가 빈다: 찾지 못함.

이진 탐색을 사용해야 할 때

사용해야 할 때피해야 할 때
데이터가 이미 정렬되어 있을 때(또는 여러 번 탐색할 때)데이터가 정렬되어 있지 않고 한 번만 탐색할 때 — 먼저 정렬하면 O(n log n)이 든다
컬렉션이 빠른 임의 접근을 지원할 때(배열)순차 접근만 가능할 때(연결 리스트)
데이터셋이 클 때 — O(log n)은 대규모에서 빛난다데이터셋이 아주 작을 때 — 단순 순회도 그만큼 빠르고 더 간단하다

Binary Search 코드

Python, JavaScript, Java, C++, C, Pseudocode로 작성된 깔끔하고 실행 가능한 Binary Search 구현입니다. 언어를 선택해 코드를 복사하거나 Coddy 플레이그라운드에서 바로 열어보세요.

Python로 구현한 Binary Search 코드

Python
1def binary_search(a, target):2    lo, hi = 0, len(a) - 13    while lo <= hi:4        mid = (lo + hi) // 25        if a[mid] == target:6            return mid7        if a[mid] < target:8            lo = mid + 1  # search the right half9        else:10            hi = mid - 1  # search the left half11    return -112
13
14nums = [1, 2, 3, 5, 7, 8, 9]  # must be sorted15print("Index of 5:", binary_search(nums, 5))16print("Index of 4:", binary_search(nums, 4))
이 코드를 Python 플레이그라운드에서 실행하기

이진 탐색 FAQ

이진 탐색의 시간 복잡도는 어떻게 되나요?
평균과 최악의 경우 O(log n)입니다. 비교할 때마다 남은 탐색 범위가 절반으로 줄어들기 때문입니다. 첫 번째 가운데 요소가 목표 값인 최선의 경우는 O(1)입니다. 반복 버전은 O(1)의 추가 공간을 사용합니다.
이진 탐색은 왜 정렬된 배열이 필요한가요?
절반으로 줄이는 단계는 순서에 의존합니다. 목표 값과 가운데 요소를 비교해서 어느 절반을 버릴지 알 수 있는 것은, 가운데 왼쪽이 모두 더 작고 오른쪽이 모두 더 클 때뿐입니다. 정렬되지 않은 데이터에서는 이 추론이 성립하지 않으므로 선형 탐색을 쓰거나 먼저 정렬하세요.
이진 탐색과 선형 탐색의 차이는 무엇인가요?
선형 탐색은 요소를 하나씩 훑으며(O(n)) 어떤 배열에서도 동작합니다. 이진 탐색은 정렬된 배열의 탐색 범위를 절반씩 줄이지만(O(log n)) 정렬된 입력이 필요합니다. 요소가 몇 개뿐이라면 차이는 미미하지만, 규모가 커지면 이진 탐색이 압도적으로 유리합니다.
이진 탐색에는 비교가 몇 번 필요한가요?
최대 약 log2(n) + 1번입니다. 비교 10번으로 1,000개, 20번으로 1,000,000개를 처리할 수 있습니다. 이 로그적 증가야말로 정렬된 데이터에서 기본 탐색 방법이 되는 이유입니다.
이진 탐색의 고전적인 오버플로 버그는 무엇인가요?
가운데를 (lo + hi) / 2로 계산하면 lo + hi가 타입의 최댓값을 넘을 때 고정 크기 정수가 오버플로될 수 있습니다. 안전한 형태는 mid = lo + (hi - lo) / 2입니다. Python에서는 문제가 되지 않지만(임의 정밀도 정수), Java/C/C++에서는 실제로 일어난 유명한 버그입니다.
이진 탐색과 이진 탐색 트리는 같은 건가요?
절반으로 나누는 아이디어는 같지만 구조가 다릅니다. 이진 탐색은 정렬된 배열 위에서 동작하는 알고리즘이고, 이진 탐색 트리는 키를 정렬된 상태로 유지하는 연결 자료 구조로, 탐색이 각 노드에서 왼쪽 또는 오른쪽으로 내려갑니다.
Coddy programming languages illustration

Coddy로 알고리즘을 마스터하세요

시작하기