백준 1655 가운데를 말해요 자바

자이로 체펠리·2021년 6월 14일
0

문제

수빈이는 동생에게 "가운데를 말해요" 게임을 가르쳐주고 있다. 수빈이가 정수를 하나씩 외칠때마다 동생은 지금까지 수빈이가 말한 수 중에서 중간값을 말해야 한다. 만약, 그동안 수빈이가 외친 수의 개수가 짝수개라면 중간에 있는 두 수 중에서 작은 수를 말해야 한다.

예를 들어 수빈이가 동생에게 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줄에 걸쳐 수빈이의 동생이 말해야하는 수를 순서대로 출력한다.

풀이

문제를 읽고나서 heap을 사용하는 것은 알았으니 이렇게 최대/최소 힙 두개를 붙여서 중간값을 탐색하는 것은 생각도 하지 못했다. 힙의 성격을 이용하면 그렇게 어려울 것은 없는 문제 였으나(물론 모르는 내입장에서는 어려웠다.), 힙을 사용해도 시간 초과가 발생하였다. 이유는 매 loop당 프린트를 하는 것에 시간 초과의 이유였다. StringBuilder를 사용하여 한번에 출력하니 해결 되었다.
백준을 풀면서 알고리즘 말고도 놓치고 지나가는 것을 많이 알게 되는것 같다.

import java.util.*;
public class Main{
    public static void main(String[] args){
        StringBuilder stringBuilder = new StringBuilder();
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        PriorityQueue<Integer> max = new PriorityQueue<>((o1,o2)->o2-o1);
        PriorityQueue<Integer> min = new PriorityQueue<>();
        
        for(int i=0; i<n;i++){
            int N=in.nextInt();
            if((i+1)%2==0){
                min.add(N);
            }else{
                max.add(N);
            }
            if(!min.isEmpty()&&min.peek()<max.peek()){
                int tmp= min.poll();
                min.add(max.poll());
                max.add(tmp);
            }
            stringBuilder.append(max.peek()).append("\n");
        }
        System.out.println(stringBuilder);
    }
}
profile
"경의를 표해라. 경의를 갖고 회전의 다음 단계로 나아가는 거다…… [LESSON 4] 다."

0개의 댓글