본 내용은 "이것이 코딩 테스트다(한빛미디어)"자료를 참고하였습니다.
순차 탐색: 리스트 안에 있는 특정한 데이터를 찾기 위해 앞에서부터 데이터를 하나씩 확인하는 방법
이진 탐색: 정렬되어 있는 리스트에서 탐색의 범위를 절반씩 좁혀가며 데이터를 탐색하는 방법
※ mid = (start + end) // 2
'''재귀함수 방식'''
def binary_search(A, start, end, target):
# return index of target in A[start] ... A[end]
if start > end: return None
mid = (start + end)//2
if target == A[mid]: #값을 찾았다!
return mid
elif target < A[mid]:
return binary_search(A, start, mid-1, target)
else:
return binary_search(A, mid+1, end, target)
'''반복문 방식'''
def binary_search2(A, start, end, target):
while start <= end:
mid = (start+end)//2
if target == A[mid]: #값을 찾았다!
return mid
elif target < A[mid]:
end = mid - 1
else:
start = mid + 1
return None
from binsect import binsect_left, binsect_right
A = [1, 2, 4, 4, 8]
x = 4
print(binsect_left(A, x)) # 2
print(binsect_right(A, x)) # 4
첫째 줄에 떡의 개수 N과 요청한 떡의 길이 M이 주어진다. (1<=N<=1,000,000, 1<=M<=2,000,000,000)
둘째 줄에는 떡의 개별 높이가 주어진다. 떡 높이의 총합은 항상 M 이상이므로, 손님은 필요한 양만큼 떡을 사갈 수 있다. 높이는 10억보다 작거나 같은 양의 정수 또는 0이다.
4 6
19 15 10 17
15
이와 같이 이진탐색을 통해서 탐색범위를 지속적으로 좁히면서 시작점과 끝점의 위치를 조정하며 높이값(중간점=H)를 매번 바꾸며 해당 높이에서 잘랐을때 떡의 총 길이가 적합한지 체크한다.
# 떡의 개수(N)와 요청한 떡의 길이(M)을 입력
n, m = list(map(int, input().split(' ')))
# 각 떡의 개별 높이 정보를 입력
array = list(map(int, input().split()))
# 이진 탐색을 위한 시작점과 끝점 설정
start = 0
end = max(array)
'''
max = array[0]
for i in range(1, len(array)):
if max < array[i]:
max = array[i]
end = max
'''
# 이진 탐색 수행 (반복문 방식)
result = 0
while(start <= end):
total = 0 # 잘린 떡의 총 길이 저장
mid = (start + end) // 2
for x in array:
# 잘랐을 때의 떡볶이 양 계산
if x > mid:
total += x - mid
# 떡볶이 양이 부족한 경우 더 많이 자르기 (오른쪽 부분 탐색)
if total < m:
end = mid - 1
# 떡볶이 양이 충분한 경우 덜 자르기 (왼쪽 부분 탐색)
else:
result = mid # 최대한 덜 잘랐을 때가 정답이므로, 여기에서 result에 기록
start = mid + 1
# 정답 출력
print(result)
7 2
1 1 2 2 2 2 3
4
count_by_range는 많이 사용되는 함수이므로 알아두면 좋음
'''binsect 라이브러리 사용'''
from binsect import binsect_left, binsect_right
# 값이 [left_value, right_value]인 데이터의 개수를 반환하는 함수
def count_by_range(A, left_value, right_value):
right_index = binsect_right(A, right_value)
left_index = binsect_left(A, left_value)
return right_index - left_index
# 데이터의 개수 N, 찾고자 하는 값 x 입력받기
n, x = map(int, input().split())
# 전체 데이터 입력받기
A = list(map(int, input().split()))
count = count_by_range(A, x, x)
#값이 x인 원소가 존재하지 않는다면
if count == 0:
print(-1)
else:
print(count)
'''라이브러리 사용x'''
# 데이터의 개수 N, 찾고자 하는 값 x 입력받기
N, x = map(int, input().split())
# 전체 데이터 입력받기
data = list(map(int, input().split()))
start = 0
end = len(data) - 1
total = 0
while start <= end:
mid = (start + end) // 2
if x == data[mid]:
for i in range(mid, -1, -1):
if data[i] == x:
total += 1
else:
break
for j in range(mid + 1, len(data)):
if data[j] == x:
total += 1
else:
break
break
elif x < data[mid]:
end = mid - 1
else:
start = mid + 1
#값이 x인 원소가 존재하지 않는다면
if total == 0:
print(-1)
else:
print(total)