[Algorithm] 순차 탐색(Sequential Search)과 이진 탐색(Binary Search)

순차 탐색

앞에서부터 하나씩 차례대로 탐색하는 방법

array = [3, 1, 7, 5, 9]
for i in range(len(array)):
    if array[i] == 7:
        print(i)
        break

리스트를 차례대로 순회하므로 시간 복잡도는 O(N)이다.

 

 


이진 탐색

정렬된 리스트에 대하여 찾으려는 데이터와 중간 지점의 데이터를 비교해나가며 탐색하는 방법

  • 순차 탐색과 달리 정렬이 되어 있어야 사용할 수 있다.
  • 중간이 정확히 안 나누어질 때는 소수점 이하를 버린다.
  • 시간 복잡도는 O(logN)이다.

구현

def binary_search(array, target, start, end):
    while start <= end:
        middle = (start + end) // 2
        if target > array[middle]:
            start = middle + 1
        elif target < array[middle]:
            end = middle - 1
        else:
            return middle
    return None

array = [1, 3, 5, 7, 9]
target = 7
index = binary_search(array, target, 0, len(array) - 1)
print(index) if index != None else print("원소가 존재하지 않습니다.")

 


이진 탐색을 사용하는 경우

찾아야 할 자료가 여러 개인 경우

  • 총 데이터 수가 N개, 찾아야 할 자료가 M개일 때 순차 탐색을 이용하면 O(M * N)만큼의 시간이 걸린다.
    그러나 이진 탐색을 이용하면 탐색에 O(MlogN)만큼의 시간이 걸리므로, 정렬에 너무 큰 시간을 소요하지 않는다면 M의 값이 커질수록 이진 탐색을 이용한 탐색이 더 효율적이게 된다.
  • 값의 범위가 크지 않은 경우에는 계수 정렬을 이용할 수도 있다.
  • 또한 자료의 인덱스가 아니라 단순 자료의 유무 여부를 판단하는 문제라면 집합을 이용하는 것이 더 효율적일 수도 있다.

최적화 문제를 결정 문제로 바꾸는 파라매트릭 서치 문제

정답이 될 수 있는 수의 범위를 정하고 이 범위 내에서 이진 탐색을 수행한다.

  • 1부터 100까지 라고 정하면 [1, 2, 3, ... , 99, 100] 이라는 가상의 배열이 있다고 가정
  • target 값과 가까워지기 위해 중간값을 산정할수록 항상 최적의 값에 가까워진다는 점을 이용