이분(이진) 탐색 (이하 이분탐색)은 검색 알고리즘의 기초적인 알고리즘으로 검색 범위를 줄여 나가면서 원하는 데이터를 검색하는 알고리즘이다. 이분탐색 전에 선형탐색에 대해 먼저 알아보자.
배열의 각 요소(i)를 처음부터 끝까지 순차적으로 탐색하여 주어진 항목과 일치하는 지 판단하는 검색 방법이다. javascript의 대표적인 built-in 메서드로 indexOf
, includes
, find
, findIndex
등이 있다. 순차적으로 값을 탐색하기 때문에, 배열의 정렬과는 상관이 없다.
배열의 첫번째 요소에 일치하는 값을 찾을 경우, 최선의 경우 O(1)
, 최악의 경우 배열의 마지막까지 검색하게 되므로 O(N)
을 갖는다. 즉, 배열의 길이(n)에 비례하는 O(N)
시간 복잡도를 갖는다.
function linearSearch(arr, val) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] === val) return i
}
return -1
}
linearSearch([34, 61, 2, 100, 687, 4, 1, 56], 30) // ==> -1
이분탐색의 기본 개념은 분할과 정복(Divide and Conquer)이다. 배열을 절반으로 계속 분할하며 요소를 탐색하는 방식이다. 선형탐색보다 효율적인 방식이다. 단, 배열의 요소가 순서(0-9, a-z 등)로 분류되어 있을 경우라는 조건에만 가능하다.
- javascript
function binarySearch (arr, val) {
let start = 0
let end = arr.length -1
while (start <= end) {
let middle = Math.floor((start + end) / 2)
if (arr[middle] === val) return middle
if (arr[middle] > val) end = middle - 1
else start = middle + 1
}
return -1
}
binarySearch([2, 5, 80, 150, 151, 180, 200, 310], 200)
- python
def binary_search (arr, val):
start, end = 0, arr.len() - 1
while start <= end:
mid = (start + end) // 2
if arr[middle] == val: return middle
if arr[middle] > val: end = middle - 1
else: start = middle + 1
return -1
선형 탐색과 마찬가지로 최선의 경우(middle point가 val일 경우) O(1)이며, 최악의 경우 O(log n)의 시간 복잡도를 갖는다.
거의 O(1)처럼 보인다!
log₂(8)
"2의 몇 승의 값이 8이 되는지"를 의미하며 답은 3이다.
2³ = 8
나눗셈과 곱셈이 짝인 것처럼 로그함수와 지수함수는 짝이다.
알고리즘(그래프)에서는 이진로그를 log₂ === log
라고 표현한다고 한다. n
의 로그를 찾기 위해서는 n이 1보다 작아지기 전에 2로 나눠지는 횟수를 말하는데, (아래 그림처럼)
8
은 1
보다 같거나 작아지기까지 2
로 세 번 나눠어지는 반면, 25
는 2
를 1
이 되기까지 대략 4~5번 나눠야 함을 알 수 있다.
정확한 계산이 중요한 것이 아니니 거시적인 관점에서 O(log n)
이 O(n)
보다 더 효율적이고 빠르다, n
이 커져도 시간이 별로 늘어나지 않는구나, 정도로 알도록 한다. ٩( ᐛ )و
다시 돌아가서, 이분탐색의 최악의 경우, log₂(32) = 5
이며 이는 O(log n)
의 시간 복잡도를 의미한다.
4,294,967,296개(약 43억개)의 원소가 있는 리스트에서 원하는 특정 값을 찾아낼 때 최악의 탐색 깊이(찾는 값이 없는 경우)는 딱 32회이다. 그러나 순차 탐색의 최악의 경우는 4,294,967,296회이다.
0부터 순서대로 숫자가 들어있는 리스트라고 할 때 순차탐색이 이분탐색보다 빠른 지점은 32까지. 33부터 그 나머지 구간에서는 이분탐색이 순차탐색보다 빠르다.
_이분탐색 | 나무위키
이분탐색과 관련된 알고리즘 문제로 나온 것들. 이론이 쉬운 반면 직접 문제를 구현하기 까다로운 것 같다. 난이도가 높은 편.. 🤔
이분탐색 찾아보다가 알게 되었는데, 어떤 데이터가 어떤 방식으로 들어가 있는지도 알고 있다면 이것보다 더 빠른 해시 탐색을 사용할 수 있다고 한다. (해시 탐색의 시간복잡도는 O(1)
)