반응형
💻 Problem
백준이는 동생에게 "가운데를 말해요" 게임을 가르쳐주고 있다. 백준이가 정수를 하나씩 외칠 때마다 동생은 지금까지 백준이가 말한 수 중에서 중간값을 말해야 한다. 만약, 그동안 백준이가 외친 수의 개수가 짝수개라면 중간에 있는 두 수 중에서 작은 수를 말해야 한다.
예를 들어 백준이가 동생에게 1, 5, 2, 10, -99, 7, 5를 순서대로 외쳤다고 하면, 동생은 1, 1, 2, 2, 2, 2, 5를 차례대로 말해야 한다. 백준이가 외치는 수가 주어졌을 때, 동생이 말해야 하는 수를 구하는 프로그램을 작성하시오.
💡 Approach
백준이가 숫자를 하나씩 말할 때마다 지금까지 나온 수들 중에 중간값을 말해야 한다.
지금까지 나온 숫자의 개수가 홀수면 가운데 값, 짝수면 가운데 두 개 중 작은 값이다.
순서 | 누적된 수 | 정렬 결과 | 중간값 |
1 | [1] | [1] | 1 |
2 | [1, 5] | [1, 5] | 1 |
3 | [1, 5, 2] | [1, 2, 5] | 2 |
4 | [1, 5, 2, 10] | [1, 2, 5, 10] | 2 |
5 | [1, 5, 2, 10, -99] | [-99, 1, 2, 5, 10] | 2 |
6 | [1, 5, 2, 10, -99, 7] | [-99, 1, 2, 5, 7, 10] | 2 |
7 | [1, 5, 2, 10, -99, 7, 5] | [-99, 1, 2, 5, 5, 7, 10] | 5 |
이중 힙(최대 힙 + 최소 힙)을 사용해서 중간값을 관리했다.
- 최대 힙 (left): 중간값 이하의 숫자 저장
- 최소 힙 (right): 중간값 초과 숫자 저장
이중 힙의 밸런스를 조정하여 항상 left 쪽의 top을 중간값으로 유지한다.
✏️ Solution
import sys
import heapq
input = sys.stdin.readline
N = int(input())
left = [] # 최대 힙 (중간값 포함)
right = [] # 최소 힙
for i in range(N):
num = int(input())
# 숫자가 중간값 이하면 left(최대 힙)에 삽입한다
if not left or num <= -left[0]:
heapq.heappush(left, -num)
# 숫자가 중간값보다 크면 right(최소 힙)에 삽입한다
else:
heapq.heappush(right, num)
# 힙 밸런스 조정
# mid를 기준으로 left 개수보다 right 개수가 더 많으면
# right 값을 하나 빼서 left로 이동한다
if len(left) < len(right):
heapq.heappush(left, -heapq.heappop(right))
# right 개수 + 1 보다 left 개수가 더 많으면
# left 값을 하나 빼서 right로 이동한다
elif len(left) > len(right) + 1:
heapq.heappush(right, -heapq.heappop(left))
print(-left[0])
우선순위 큐의 시간 복잡도는 logN이고 N번 반복하니 전체 시간 복잡도는 O(NlogN)이다.
N의 최댓값은 100,000이다.
10^6은 2^20으로 치환 가능하므로 시간 복잡도는 2 * 10^7이다.
반응형
'Algorithm > 백준 (BOJ)' 카테고리의 다른 글
[Python] 백준/BOJ 17086번: 아기 상어 2 (Silver 2) (0) | 2025.07.10 |
---|---|
[Python] 백준/BOJ 3197번: 백조의 호수 (Platinum 5) (0) | 2025.07.03 |
[Python] 백준/BOJ 24499번: blobyum (Silver 4) (0) | 2025.06.20 |
[Python] 백준/BOJ 28135번: Since 1973 (Bronze 3) (0) | 2025.06.15 |