본문 바로가기
Computer Science/Algorithm

이진 검색 binary search의 여러 가지 형태(파이썬 코드)

by ggyongi 2021. 6. 11.
반응형

1.

다음은 가장 잘 알려진 이진 검색 코드다.

찾으려는 값을 target으로 넣어주면 그 값에 해당하는 인덱스를 빠르게 찾아 리턴한다. 

a= [1,4,5,8,12]
def binary_search(target):
    left = 0
    right = len(a)-1
    while left <= right:
        mid = (left+right)//2
        if a[mid] == target: #find
            return mid
        elif a[mid] > target:
            right = mid -1
        else:
            left = mid + 1
    return mid

print('target:',4,  'find:',a[binary_search(4)])
print('target:',5,  'find:',  a[binary_search(5)])
print('target:',8,  'find:', a[binary_search(8)])
print('target:',12,  'find:', a[binary_search(12)])

>> target: 4 find: 4
>> target: 5 find: 5
>> target: 8 find: 8
>> target: 12 find: 12

 

2.

그러면 동일한 코드인데 리스트에 존재하지 않는 값을 찾으면 어떻게 될까?

다음을 확인해보자.

a= [1,4,5,8,12]
def binary_search(target):
    left = 0
    right = len(a)-1
    while left <= right:
        mid = (left+right)//2
        if a[mid] == target: #find
            return mid
        elif a[mid] > target:
            right = mid -1
        else:
            left = mid + 1
    return mid

print('target:',0,  'find:',a[binary_search(0)])
print('target:',2,  'find:',  a[binary_search(2)])
print('target:',6,  'find:', a[binary_search(6)])
print('target:',13,  'find:', a[binary_search(13)])

>> target: 0 find: 1
>> target: 2 find: 4
>> target: 6 find: 8
>> target: 13 find: 12

위의 결과를 살펴보면, 존재 하지 않는 값을 찾으려고 시도할때 그 근처의 값을 찾아 변환해주는 것을 볼 수 있다.

정확히 살펴보면

1. 리스트의 최솟값보다 더 작은 값을 찾으려고 시도 -> 리스트의 첫번째 값을 찾음

2. 리스트의 최댓값보다 더 큰 값을 찾으려고 시도 -> 리스트의 마지막 값을 찾음

3. 리스트의 최솟값, 최댓값 사이의 값이지만 존재하지 않는 값을 찾으려고 시도 -> 그 값보다 크면서 가장 가까운 값을 찾음

 

3.

다음으로 밑의 코드는 존재 하지 않는 값을 찾으려고 시도할 때 mid값이 아닌 right값을 리턴해주는 경우이다.

결과를 살펴보자.

a= [1,4,5,8,12]
def binary_search(target):
    left = 0
    right = len(a)-1
    while left <= right:
        mid = (left+right)//2
        if a[mid] == target: #find
            return mid
        elif a[mid] > target:
            right = mid -1
        else:
            left = mid + 1
    return right  ########## mid 대신에 right

print('target:',0,  'find:',a[binary_search(0)])
print('target:',2,  'find:',  a[binary_search(2)])
print('target:',6,  'find:', a[binary_search(6)])
print('target:',13,  'find:', a[binary_search(13)])

>> target: 0 find: 12
>> target: 2 find: 1
>> target: 6 find: 5
>> target: 13 find: 12

정확히 살펴보면

1. 리스트의 최솟값보다 더 작은 값을 찾으려고 시도 -> 인덱스 -1를 반환하여 리스트 마지막 값을 찾게 됨

2. 리스트의 최댓값보다 더 큰 값을 찾으려고 시도 -> 리스트의 마지막 값을 찾음

3. 리스트의 최솟값, 최댓값 사이의 값이지만 존재하지 않는 값을 찾으려고 시도 -> 그 값보다 작으면서 가장 가까운 값을 찾음

 

1의 문제를 보완해주기 위해 max(right,0)을 리턴해주는 편이 낫다.

a= [1,4,5,8,12]
def binary_search(target):
    left = 0
    right = len(a)-1
    while left <= right:
        mid = (left+right)//2
        if a[mid] == target: #find
            return mid
        elif a[mid] > target:
            right = mid -1
        else:
            left = mid + 1
    return max(right, 0)

print('target:',0,  'find:',a[binary_search(0)])
print('target:',2,  'find:',  a[binary_search(2)])
print('target:',6,  'find:', a[binary_search(6)])
print('target:',13,  'find:', a[binary_search(13)])

>> target: 0 find: 1
>> target: 2 find: 1
>> target: 6 find: 5
>> target: 13 find: 12

 

 

4.

left의 경우 결과는 다음과 같다.

인덱스 오류를 피하기위해 min(left, len(a)-1)을 해주면 사실상 mid랑 다를게 없어진다.

a= [1,4,5,8,12]
def binary_search(target):
    left = 0
    right = len(a)-1
    while left <= right:
        mid = (left+right)//2
        if a[mid] == target: #find
            return mid
        elif a[mid] > target:
            right = mid -1
        else:
            left = mid + 1
    return min(left, len(a)-1)

print('target:',0,  'find:',a[binary_search(0)])
print('target:',2,  'find:',  a[binary_search(2)])
print('target:',6,  'find:', a[binary_search(6)])
print('target:',13,  'find:', a[binary_search(13)])

>> target: 0 find: 1
>> target: 2 find: 4
>> target: 6 find: 8
>> target: 13 find: 12

 

 

 

비전공자 네카라 신입 취업 노하우

시행착오 끝에 얻어낸 취업 노하우가 모두 담긴 전자책!

kmong.com

댓글