BS를 이용해서 풀려했는데 시간초과로 풀수가 없었다.
그래서 풀이법을 찾는중 lower bound와 upper bound의 개념을 찾게되었다.
lower bound는 타겟인 수보다 크거나 같은 최초 위치를 찾아내고
upper bound는 타겟인 수보다 초과인 최초 위치를 찾아낸다.
물론 lower bound와 upper bound도 BS와 같이 데이터가 정렬이 되어있어야한다.
1 2 2 4 5 5 5 8 10 의 수열이 있다고 하자. 이중에서 target이 5의 lower bound와 upper bound를 찾아보자
lower bound와 upper bound는 Binary Search를 살짝 응용해서 구현할수 있다.
BS는 어떠한 target을 찾아낸뒤 return을 해도 무방한 알고리즘이지만 lowerbound와 upperbound는 start < end가 되기 직전까지 무조건 순회해야한다.(난 반복문으로 풀었다.)
코드를 보면서 BS와의 차이를 확인해보자
import sys
N = int(sys.stdin.readline().rstrip())
cards = list(map(int, sys.stdin.readline().rstrip().split()))
M = int(sys.stdin.readline().rstrip())
nums = list(map(int, sys.stdin.readline().rstrip().split()))
cards.sort()
def upper_bound(start, end, target):
while start < end:
mid = (start + end) // 2
if target >= cards[mid]:
start = mid + 1
else:
end = mid
return end + 1
def lowr_bound(start, end, target):
while start < end:
mid = (start + end) // 2
if target > cards[mid]:
start = mid + 1
else:
end = mid
return end + 1
for num in nums:
print(upper_bound(0, len(cards), num) - lowr_bound(0, len(cards), num), end=' ')
upper_bound와 lower_bound의 차이를 보면 if target > cards[mid]:
와 if target >= cards[mid]:
부분이 차이가 있는걸 볼 수가 있다. upper_bound는 target
과 cards[mid]
가 같아도 start = mid + 1
로 계속 위치를 조정하는 것을 볼 수가 있다. 이를 통해서 target보다 초과하는 첫번째 인덱스를 구할수 있다.
이 문제에서 틀렸던 부분은 end의 인자로 전달하는 값때문에 좀 틀렸다.
end로 전달하는 값을 len(cards) - 1
이 아닌 len(cards)
로 전달해야 적절한 값을 도출할수 있다, 왜냐면 upper_bound와 lower_bound에서 end + 1
을 리턴하기 때문이다.