본문 바로가기
Algorithm/Baekjoon

1655. 가운데를 말해요 (Python)

by 원만사 2022. 3. 12.
반응형
 

1655번: 가운데를 말해요

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

www.acmicpc.net

 

풀이

 가운데를 기준으로 낮은쪽을 저장하는 힙(smallerNumbers)과 높은쪽을 저장하는 힙(biggerNumbers)을 사용하여 해결하였다. smallerNumbers의 경우는 최대힙을 사용하였고 biggerNumbers의 경우는 최소힙을 사용하였다. 이는 작은 숫자들중에서는 가장 큰 숫자(smallerRep)가 가운데에 올 수 있고 큰 숫자들중에서는 가장 작은 숫자(biggerRep)가 가운데에 올 수 있기 때문이다.

 

 smallerRep와 biggerRep는 변수로 두어 따로 관리한다. 이제 숫자를 입력 받으면 다음과 같은 3가지 경우로 나누어 처리한다

 

(1) smallerRep 이하일 경우

- smallerRep 이하일 경우에는 smallerNumbers에 입력값을 넣어준다.

 

(2) smallerRep와 biggerRep 사이일 경우 

- smallerRep를 입력 받은 숫자로 바꿔주고 기존의 smallerRep값은 smallerNumbers에 넣어준다.

 

(3) biggerRep 이상일 경우

- biggerRep 이상일 경우에는 biggerNumbers에 입력값을 넣어준다.

 

 그러나 이때 한 가지 주의해야 할 것이 있다. smallerRep와 biggerRep가 전체 숫자에서 가운데에 있을 수 있으려면 smallerNumbers와 biggerNumbers에 들어있는 값의 개수의 차이가 1을 넘어서면 안된다. 예를 들어 입력값으로 (1, 2, 3, 4, 5)가 들어오면 처음 두 번에서 smaellerRep는 1이 되고 biggerRep는 2가 된다. 나머지 3, 4, 5는 biggerRep보다 크므로 biggerNumbers에만 값들이 추가되고 이렇게 되면 smaellerRep와 biggerRep는 가운데에 존재하는 숫자가 아니게 된다. 

 따라서, 값을 넣어 주고 두 힙의 원소의 개수를 비교하여 2이상 차이가 날 경우에는 두 힙의 차이를 맞춰주는 과정이 필요하다. 만약 smallerNumbers의 원소 개수가 더 많다면 다음의 과정이 진행된다.

  • biggerRep를 biggerNumbers에 넣어준다.
  • smallerRep를 biggerRep에 대입한다.
  • smallerRep는 smallerNumbers에서 최댓값으로 설정한다. 

 위와 같은 과정을 통해서 두 힙의 원소의 개수 차이를 맞춰주고 smaellerRep와 biggerRep는 전체 숫자 중 가운데에 있는 숫자들로 유지할 수 있다.

 

 마지막 출력에서는 홀수 번째로 입력한 값의 경우에는 lowerNumbers와 higherNumbers중 더 많은 값을 가지고 있는 쪽의 대표 숫자를 출력해 주면 되고 짝수 번째로 입력한 값의 경우에는 lowerRep를 출력해 주면 된다.

 

코드

import heapq
import sys
INF = float('INF')
input = sys.stdin.readline


# 두 힙의 길이를 조정하기 위한 함수
def balance(isSmaller):
    global smallerRep, biggerRep

    if isSmaller: # 작은 쪽 숫자들이 더 많을 경우
        heapq.heappush(biggerNumbers, biggerRep) # 큰 쪽 숫자에 기존의 큰 값의 대표를 추가해주고
        biggerRep = smallerRep # 작은 값의 대표를 큰 값의 대표로 바꿔준다
        smallerRep = -heapq.heappop(smallerNumbers) # 이제 작은 값의 대표는 smallerNumbers에서 새로 갖고온다.
    else: # 큰 쪽 숫자들이 더 많을 경우
        heapq.heappush(smallerNumbers, -smallerRep) # 작은 쪽 숫자에 기존의 smallerRep를 추가해주고
        smallerRep = biggerRep # biggerRep를 smallerRep로 바꿔준다
        biggerRep = heapq.heappop(biggerNumbers) # 이제 biggerRep는 biggerNumbers에서 새로 갖고온다.


if __name__ == '__main__':
    N = int(input())
    smallerNumbers = [] # 가운데를 기준으로 작은 숫자들을 모아 놓는 힙 (최대힙)
    biggerNumbers = [] # 가운데를 기준으로 큰 숫자들을 뫃아 놓는 힙 (최소힙)
    smallerRep = INF # 작은 숫자들 중 가장 큰 숫자 (가운데에 있을 수 있는 숫자)
    biggerRep = -INF # 큰 숫자들 중 가장 작은 숫자 (가운데에 있을 수 있는 숫자)

    if N == 1:
        print(int(input()))
        sys.exit()

    for _ in range(2): # 첫 숫자 2개는 작은 숫자 출력
        number = int(input())
        smallerRep = min(smallerRep, number)
        biggerRep = max(biggerRep, number)
        print(smallerRep)

    # 두 힙에 INF를 넣는 이유는 가운데에 있을 수 있는 숫자는 xxRep 변수에 저장해두고 힙에는 넣지 않기 때문
    # 두 힙의 길이를 비교해야 하는 경우가 있어 임시로 INF를 넣는다 
    heapq.heappush(smallerNumbers, INF) 
    heapq.heappush(biggerNumbers, INF)

    for i in range(3, N+1):
        number = int(input()) # 입력 받은 숫자 

        if number <= smallerRep: # 입력 받은 숫자가 smallerRep 이하일 때, smallerNumbers에 추가
            heapq.heappush(smallerNumbers, -number)
        elif smallerRep < number < biggerRep: # 두 중간 값 사이일 경우
            heapq.heappush(smallerNumbers, -smallerRep) # 기존의 smallerRep는 smallerNumbers에 넣어주고
            smallerRep = number # smallerRep를 입력 값으로 변경
        else: # 입력 받은 숫자가 biggerRep 이상일 때
            heapq.heappush(biggerNumbers, number) # biggerNumbers에 추가 


        # 두 힙의 길이의 차이가 2 이상이 될 경우
        # smallerRep 또는 biggerRep가 가운데 숫자에서 벗어나게 되므로 조정이 필요함
        if abs(len(smallerNumbers) - len(biggerNumbers)) > 1:
            if len(smallerNumbers) > len(biggerNumbers):
                balance(isSmaller=True)
            else:
                balance(isSmaller=False)


        if i % 2 == 1: # 외친 수의 개수가 홀수일 경우, 더 많은 숫자를 갖고 있는 쪽의 대표값이 가운데 숫자가 된다
            if len(smallerNumbers) > len(biggerNumbers): 
                print(smallerRep)
            else:
                print(biggerRep)
        else: # 짝수개일 경우에는 두 숫자가 가운데 숫자가 되고 이 중 더 작은 값인 smallerRep를 출력해준다.
            print(smallerRep)
반응형

'Algorithm > Baekjoon' 카테고리의 다른 글

1405. 미친 로봇 (Python)  (0) 2022.03.15
2616. 소형기관차 (Python)  (0) 2022.03.13
3078. 좋은 친구 (Python)  (0) 2022.03.10
9663. N-Queen (Python)  (0) 2022.03.08
9466. 텀 프로젝트 (Python)  (0) 2022.03.08

댓글