문제링크
https://www.acmicpc.net/problem/1655
1655번: 가운데를 말해요
첫째 줄에는 백준이가 외치는 정수의 개수 N이 주어진다. N은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수이다. 그 다음 N줄에 걸쳐서 백준이가 외치는 정수가 차례대로 주어진다. 정수는 -1
www.acmicpc.net
문제설명
문제
백준이는 동생에게 "가운데를 말해요" 게임을 가르쳐주고 있다. 백준이가 정수를 하나씩 외칠때마다 동생은 지금까지 백준이가 말한 수 중에서 중간값을 말해야 한다. 만약, 그동안 백준이가 외친 수의 개수가 짝수개라면 중간에 있는 두 수 중에서 작은 수를 말해야 한다.
예를 들어 백준이가 동생에게 1, 5, 2, 10, -99, 7, 5를 순서대로 외쳤다고 하면, 동생은 1, 1, 2, 2, 2, 2, 5를 차례대로 말해야 한다. 백준이가 외치는 수가 주어졌을 때, 동생이 말해야 하는 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에는 백준이가 외치는 정수의 개수 N이 주어진다. N은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수이다. 그 다음 N줄에 걸쳐서 백준이가 외치는 정수가 차례대로 주어진다. 정수는 -10,000보다 크거나 같고, 10,000보다 작거나 같다.
출력
한 줄에 하나씩 N줄에 걸쳐 백준이의 동생이 말해야 하는 수를 순서대로 출력한다.
예제 입력 1
7
1
5
2
10
-99
7
5
예제 출력 1
1
1
2
2
2
2
5
문제풀이
시간초과난 풀이
시간초과가 날것으로 예상했는데 역시나였다.
해결방법
우선순위 큐를 이용하자!
두개의 힙을 만들어 하나는 최소힙, 다른 하나는 최대힙으로 구현하자.
핵심은
leftHeap의 첫번째 원소에 중간값이 위치하게 만들면 된다.
rightHeap의 첫번째 원소가 leftHeap의 첫번째원소보다 크다면 중간값을 구할 수 없게 되므로
매 루프시 조건문을 통해 exchage하자!
이렇게 하면 매 루프시 sort를 시행하는 것보다 연산횟수 측면에서 단연 효율적이다.
코드
import sys
import heapq
input = sys.stdin.readline
N = int(input())
leftHeap = []
rightHeap = []
for i in range(N):
data = int(input())
if len(leftHeap) == len(rightHeap):
# 최대힙으로 구현
heapq.heappush(leftHeap, -data)
else:
# 최소힙으로 구현
heapq.heappush(rightHeap, data)
# leftHeap의 첫번째 원소를 중간값으로 만들기 위해 교환.
if rightHeap and rightHeap[0] < -leftHeap[0]:
l = heapq.heappop(leftHeap)
r = heapq.heappop(rightHeap)
heapq.heappush(rightHeap, -l)
heapq.heappush(leftHeap, -r)
print(-leftHeap[0])
'알고리즘 > 백준' 카테고리의 다른 글
[백준 1759] 암호 만들기 (with Python / 백트래킹) (0) | 2023.09.28 |
---|---|
[백준 1987] 알파벳 (with Python / 백트래킹) (0) | 2023.09.27 |
[백준 1715] 카드 정렬하기 (with Python / 그리디 + 우선순위큐) (1) | 2023.09.27 |
[백준 11286] 절댓값 힙 (with Python / 우선순위 큐) (0) | 2023.09.26 |
[백준 14500] 테트로미노 (with Python / 구현) (0) | 2023.09.23 |