중앙값은 본인보다 작은 값들의 개수와 본인보다 큰 값들의 개수가 동일함
중앙값의 특성을 활용해, 최대힙과 최소힙으로 중앙값 탐색을 쉽게 만들 수 있음
[코드 구성]
import sys
import heapq
N = int(sys.stdin.readline())
# [목표] max_h의 루트가 항상 전체 배열의 중앙값이 될 수 있도록 한다.
# - max_h의 길이는 min_h의 길이보다 항상 1만큼 크거나 같게 유지함
# - max_h에는 항상 max_h의 루트(중앙값)보다 작은 값들이 모여 있음
# - min_h에는 항상 max_h의 루트(중앙값)보다 큰 값이 모여 있음
max_h, min_h = [], []
for _ in range(N):
v = int(sys.stdin.readline())
# 1) 두 heap을 번갈아 가며 새로운 value를 추가
if len(max_h) == len(min_h):
heapq.heappush(max_h, (-v, v))
else:
heapq.heappush(min_h, (v, v))
# 2) max_h의 루트가 min_h의 루트보다 더 크면 교환
if min_h and max_h[0][1] > min_h[0][1]:
lg = heapq.heappop(max_h)
sm = heapq.heappop(min_h)
# 주의: 부호를 반대로 변경해주어야 함
heapq.heappush(max_h, (-sm[0], sm[1]))
heapq.heappush(min_h, (-lg[0], lg[1]))
print(max_h[0][1])
def parent(i):
return (i-1)//2
def left(i):
return i*2+1
def right(i):
return i*2+2
def max_heapify(arr, i):
l, r = left(i), right(i)
lg = i
if l < len(arr) and arr[l] > arr[lg]:
lg = l
if r < len(arr) and arr[r] > arr[lg]:
lg = r
if lg != i:
arr[lg], arr[i] = arr[i], arr[lg]
max_heapify(arr, lg)
def max_extract(heap):
L = len(heap)
if L < 1:
return False
max_value = heap[0]
heap[0] = heap[L-1]
heap.pop()
max_heapify(heap, 0)
return max_value
def max_insert(heap, v):
heap.append(v)
i = len(heap) - 1
while i > 0: # i == 0 이면 root
p = parent(i)
if heap[p] >= heap[i]:
break
heap[p], heap[i] = heap[i], heap[p]
i = p
def min_heapify(arr, i):
l, r = left(i), right(i)
sm = i
if l < len(arr) and arr[l] < arr[sm]:
sm = l
if r < len(arr) and arr[r] < arr[sm]:
sm = r
if sm != i:
arr[i], arr[sm] = arr[sm], arr[i]
min_heapify(arr, sm)
def min_extract(heap):
L = len(heap)
if L < 1:
return False
min_value = heap[0]
heap[0] = heap[L-1]
heap.pop()
min_heapify(heap, 0)
return min_value
def min_insert(heap, v):
heap.append(v)
i = len(heap) - 1
while i > 0:
p = parent(i)
if heap[p] <= heap[i]:
break
heap[p], heap[i] = heap[i], heap[p]
i = p
import sys
N = int(sys.stdin.readline())
# [목표] max_h의 루트가 항상 전체 배열의 중앙값이 될 수 있도록 한다.
# - max_h의 길이는 min_h의 길이보다 항상 1만큼 크거나 같게 유지함
# - max_h에는 항상 max_h의 루트(중앙값)보다 작은 값들이 모여 있음
# - min_h에는 항상 max_h의 루트(중앙값)보다 큰 값이 모여 있음
max_h, min_h = [], []
for _ in range(N):
v = int(sys.stdin.readline())
# 1) 두 heap을 번갈아 가며 새로운 value를 추가
if len(max_h) == len(min_h):
max_insert(max_h, v)
else:
min_insert(min_h, v)
# 2) max_h의 루트가 min_h의 루트보다 더 크면 교환
if min_h and max_h[0] > min_h[0]:
lg = max_extract(max_h)
sm = min_extract(min_h)
max_insert(max_h, sm)
min_insert(min_h, lg)
print(max_h[0])