Coding Test/BaekJoon_Python

백준 1655 <가운데를 말해요> Python

JunOnJuly 2023. 10. 25. 21:31
728x90

https://www.acmicpc.net/problem/1655

 

1655번: 가운데를 말해요

첫째 줄에는 백준이가 외치는 정수의 개수 N이 주어진다. N은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수이다. 그 다음 N줄에 걸쳐서 백준이가 외치는 정수가 차례대로 주어진다. 정수는 -1

www.acmicpc.net


수가 들어올 때 마다 정렬이 되어야 한다

그러므로 정렬에 많은 시간이 소요되면 안된다

다른 순서는 필요없고 중간만 맞으면 된다

 

라는 특성이 문제를 푸는데 가장 중요한 포인트였습니다.

우선 힙(우선순위큐)를 사용했는데, 이유는 다음과 같습니다.

 

수가 들어올 때 마다 정렬이 되어야 한다

-> 힙 삽입으로 해결

정렬에 많은 시간이 소요되면 안된다

-> 힙 정렬로 해결

다른 순서는 필요없고 중간만 맞으면 된다

-> 힙은 중간 순서는 맞지 않을 수 있지만 가장 우선순위가 높은 수는 알 수 있다, 힙을 두 개 쓰자

 

결국 속도가 가장 빠르기 때문에 썼습니다.

심지어 최대힙과 최소힙 두 개를 쓰면 최적의 경우 한번에 정렬을 하나의 힙만 해도 되기 때문에 더 빠르다고 볼 수 있습니다.

 

기본 아이디어는 '입력된 수들의 리스트 중 앞 부분 절반은 최대 힙으로, 뒷 부분 절반은 최소 힙으로 생각하고 두 힙을 합치면 다른 순서는 몰라도 가운데는 항상 찾을 수 있다는 것' 입니다.


# 힙 사용
import heapq
# 편하게 하려고 deque 사용
from collections import deque
import sys


def solution(N, num_list):
    # 최대 힙
    max_heap = []
    # 최소 힙
    min_heap = []
    # deque, popleft 쓰려고..
    num_list = deque(num_list)
   
    i = 0
    while True:
        # 모두 넣으면 끝
        if not num_list:
            break
        # 홀수일 때는 max heap 에
        # max heap 이라 - 붙여서 입력
        if not i%2:
            heapq.heappush(max_heap, -num_list.popleft())
        # 짝수일 때는 min heap 에 번갈아서 넣어줌
        else:
            heapq.heappush(min_heap, num_list.popleft())
        # max heap 의 최댓값과 min heap 의 최솟값을 비교해서 교환
        # max heap 과 교환이라 - 붙여서 비교, 교환
        if i and -max_heap[0] > min_heap[0]:
            max_pop = -heapq.heappop(max_heap)
            min_pop = heapq.heappop(min_heap)
           
            heapq.heappush(max_heap, -min_pop)
            heapq.heappush(min_heap, max_pop)
           
        # i 증가
        i += 1
        # 출력
        # max heap 이라 - 붙여서 출력
        print(-max_heap[0])

           
N = int(sys.stdin.readline())
num_list = [int(sys.stdin.readline()) for _ in range(N)]
solution(N, num_list)
728x90