https://www.acmicpc.net/problem/10816
10816번: 숫자 카드 2
첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,
www.acmicpc.net
이분 탐색으로 아래 풀이 처럼 풀었는데도 시간초과가 뜬다.
# BOJ_10816
# 입력
n = int(input())
cards = list(map(int, input().split()))
m = int(input())
show_cards = list(map(int, input().split()))
# 두 카드 목록 모두 오름차순으로 정렬한다.
cards.sort()
# 카드 갯수를 세는 함수
def count_card(cards, show_card):
# 이분탐색으로 제시된 카드 찾는다.
start, end = 0, n - 1
while start <= end:
mid = (start + end) // 2
if cards[mid] == show_card:
# show_card가 시작되는 부분, 끝나는 부분 인덱스를 각각 구한다.
card_start, card_end = mid, mid
while cards[card_start] == show_card:
if card_start > 0:
card_start -= 1
else:
card_start -= 1
break
while cards[card_end] == show_card:
if card_end < len(cards) - 1:
card_end += 1
else:
card_end += 1
break
return card_end - card_start - 1
elif cards[mid] > show_card:
end = mid - 1
else:
start = mid + 1
return 0
# 카드 갯수를 각각 출력해준다.
for show_card in show_cards:
print(count_card(cards, show_card))
원인을 찾던 중에 upper bound / lower bound 개념을 추가해야 한다는 걸 알았다.
https://velog.io/@himinhee/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Lower-bound-Upper-bound-python
Lower bound, Upper bound (python)
파이썬 모듈 중 bisect에는 lower bound, upper bound의 기능을 하는 함수가 존재한다. 👉사용법 보러 가기
velog.io
그리고 위 개념을 한번에 쓸 수 있는 모듈: bisect 모듈
https://velog.io/@himinhee/python-bisect%EB%AA%A8%EB%93%88
[python] bisect모듈
📕 추가 파이썬 bisect모듈의 공식 문서
velog.io
bisect 모듈을 이용하여 아래와 같이 구현하니 맞았다.
기존
if cards[mid] == show_card:
# show_card가 시작되는 부분, 끝나는 부분 인덱스를 각각 구한다.
card_start, card_end = mid, mid
while cards[card_start] == show_card:
if card_start > 0:
card_start -= 1
else:
card_start -= 1
break
while cards[card_end] == show_card:
if card_end < len(cards) - 1:
card_end += 1
else:
card_end += 1
break
return card_end - card_start - 1
bisect으로 시간 복잡도 줄인 코드
if cards[mid] == show_card:
# show_card가 시작되는 부분, 끝나는 부분 인덱스를 각각 구한다.
card_start = (bisect.bisect_left(cards, show_card))
card_end = (bisect.bisect_right(cards, show_card))
return card_end - card_start
두 코드 모두 같은 기능(특정 숫자의 시작과 끝 범위 찾기)을 구현한 코드이다.
# BOJ_10816
import bisect
# 입력
n = int(input())
cards = list(map(int, input().split()))
m = int(input())
show_cards = list(map(int, input().split()))
# 두 카드 목록 모두 오름차순으로 정렬한다.
cards.sort()
# 카드 갯수를 세는 함수
def count_card(cards, show_card):
# 이분탐색으로 제시된 카드 찾는다.
start, end = 0, n - 1
while start <= end:
mid = (start + end) // 2
if cards[mid] == show_card:
# show_card가 시작되는 부분, 끝나는 부분 인덱스를 각각 구한다.
card_start = (bisect.bisect_left(cards, show_card))
card_end = (bisect.bisect_right(cards, show_card))
return card_end - card_start
elif cards[mid] > show_card:
end = mid - 1
else:
start = mid + 1
return 0
# 카드 갯수를 각각 출력해준다.
for show_card in show_cards:
print(count_card(cards, show_card))
'Computer Science > Algorithm' 카테고리의 다른 글
약점보완: Dynamic Programming (0) | 2023.02.09 |
---|---|
[백준] 2164번 카드2 - 시간초과, 짝수 홀수 인덱스만 추출하기 (0) | 2023.02.02 |
[백준] 1654번 랜선 자르기, 시간초과 - 이분탐색(풀이 암기) (0) | 2023.01.25 |
[백준] 10816번 숫자 카드2, 시간 초과 - 이진탐색 + 알파 (0) | 2023.01.21 |
[백준] 2562번 최댓값, 줄 단위 정수 리스트로 입력 받기 (0) | 2023.01.17 |