[알고리즘] 이분탐색
(문제) 이분탐색
임의의 N개의 숫자가 입력으로 주어집니다.
N개의 수를 오름차순으로 정렬한 다음 N개의 수 중 한 개의 수인 M이 주어지면 이분검색
으로 M이 정렬된 상태에서 몇 번째에 있는지 구하는 프로그램을 작성하세요.
단 중복값은 존재하지 않습니다.
입력설명
첫 줄에 한 줄에 자연수 N(3<=N<=1,000,000)과 M이 주어집니다.
두 번째 줄에 N개의 수가 공백을 사이에 두고 주어집니다.
출력설명
첫 줄에 정렬 후 M의 값의 위치 번호를 출력한다.
테스트케이스
입력예제 | 출력예제 |
---|---|
8 32 23 87 65 12 57 32 99 81 |
3 |
15 99 73 32 31 49 94 37 40 62 78 66 27 100 99 29 9 |
14 |
30 57 6 32 38 1 28 76 51 8 98 88 74 60 65 57 97 63 56 99 85 5 13 100 61 36 44 50 62 41 91 9 |
16 |
해결방법
숫자 up & down을 생각해보면 간단하다.
우선 정렬을 해야한다.
정렬한 리스트에서 맨 앞 인덱스를 LT로
맨 마지막 인덱스를 RT로 포인터를 잡는다.
LT와 RT의 중앙 MID를 잡기 위해서 (LT + RT) // 2를 한다.
자! 아까 말한 숫자 UP & DOWN을 생각해보자.
A라는 사람에게 1 ~ 50 까지의 숫자 중에 하나의 숫자를 생각해 보라고 해보자.
우리가 이 사람이 생각한 숫자를 맞추려고 할 때, 중앙의 수 기준으로 자르지 않나?
25 인가?
물어보고 그 숫자가 아니면 A라는 사람은 A가 결정한 숫자가 내가 말한 숫자보다 UP인지 DOWN인지 알려준다.
이때 만약 A가 DOWN이라고 하면 우리는 25 이상인 숫자는 다 배제한다.
그러고 다시 1 ~ 25 사이의 숫자를 우리는 생각하여 물어 볼 것이고, 이것을 반복하여 숫자를 찾을 것이다.
이분탐색
방법은 이 방법과 동일하다.
만약 MID의 숫자가 결정한 숫자 보다 작으면 RT는 MID의 값이 되고
MID의 숫자가 결정한 숫자보다 클 경우 LT는 MID의 값이 되는 것이다.
LT가 만약 RT 이상이 될 경우 이 반복은 종료한다.
코드
n, m = map(int, input().split())
arr = list(map(int, input().split()))
# 이분 검색을 위한 정렬
arr.sort()
LT = 0
RT = len(arr) - 1
# 만약 끝까지 했는데, 동일한 구간이 생기는데, 이때 맞는 것이다.
# 시간 복잡도 0 (lon N)
while LT <= RT:
MID = (LT + RT) // 2
# MID + 1 혹은 MID - 1 하는 이유는 MID가 아니기 때문
if arr[MID] == m:
break
if arr[MID] > m:
RT = MID-1
elif arr[MID] < m:
LT = MID+1
print(MID+1)
댓글남기기