[백준 1655] 가운데를 말해요(Java)

최민길(Gale)·2023년 1월 30일
1

알고리즘

목록 보기
26/172

문제 링크 : https://www.acmicpc.net/problem/1655

이 문제는 우선 순위 큐를 이용하여 풀 수 있습니다. 중간값을 체크하기 위해 중간값 기준 작은 수를 담고 있는 우선순위 큐와 중간값 기준 큰 수를 담고 있는 우선순위 큐를 두 개 만듭니다. 이 때 작은 큐의 경우 큰 값과의 비교를 위해 내림차순 정렬을 따로 하여 진행합니다.

여기서 주의할 점은 작은 큐와 큰 큐의 차이를 1 이하로 유지하는 것입니다. 우선 순위 큐 특성상 FIFO 방식으로 한번에 하나의 값만을 참조할 수 있습니다. 따라서 한 쪽에 데이터가 몰릴 경우 중간값이 아닌 극단에 치우친 값이 출력됩니다. 따라서 데이터를 추가할 때 두 큐의 차이가 1 이하로 유지하면서 작은 큐와 큰 큐의 데이터를 비교하면서 추가하면 됩니다.

다음은 코드입니다.

import java.util.*;
import java.io.*;

public class Main{
    static int N;
    // 중간값 출력을 위해 중간값 기준 작은 우선순위 큐와 큰 우선순위 큐를 설정
    // 작은 큐의 경우 가장 큰 값과 비교해야 하므로 내림차순 정렬
    static PriorityQueue<Integer> small = new PriorityQueue<>(Collections.reverseOrder());
    static PriorityQueue<Integer> big = new PriorityQueue<>();
    // 결과값 담는 큐
    static Queue<Integer> res = new LinkedList<>();

    static void putData(int prev, int curr){
        // 현재 입력받은 수가 더 크다면 이전 수를 작은 큐에, 현재 수를 큰 큐에 추가
        if(prev < curr){
            small.add(prev);
            big.add(curr);
        }
        // 현재 입력받은 수가 더 작다면 이전 수를 큰 큐에, 현재 수를 작은 큐에 추가
        else{
            big.add(prev);
            small.add(curr);
        }
    }

    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        N = Integer.parseInt(br.readLine());

        for(int i=0;i<N;i++){
            int curr = Integer.parseInt(br.readLine());

            // 작은 큐에 데이터가 없다면 작은 큐에 데이터 삽입
            if(small.isEmpty()) small.add(curr);
            // 큰 큐에 데이터가 없다면 작은 큐의 데이터와 비교해서 큰 값을 큰 큐로 옮기기
            else if(big.isEmpty()){
                int prev = small.poll();
                putData(prev,curr);

            }
            // 두 큐에 모두 데이터가 있다면 두 큐의 크기에 따라 다르게 추가
            else{
                // 작은 큐의 크기가 큰 큐의 크기보다 크다면 작은 큐의 데이터를 뽑아 현재 값과 비교하기
                if(small.size() > big.size()){
                    int prev = small.poll();
                    putData(prev,curr);
                }
                // 큰 큐의 크기가 작은 큐의 크기보다 크다면 큰 큐의 데이터를 뽑아 현재 값과 비교하기
                else if(small.size() < big.size()){
                    int prev = big.poll();
                    putData(prev,curr);
                }
                // 두 큐의 크기가 같다면 현재 입력값의 크기에 따라 적합한 위치에 추가
                else{
                    // 현재 입력값이 작은 큐의 가장 큰 값보다 작거나 같다면 작은 큐에 추가
                    if(small.peek() >= curr) small.add(curr);
                    // 현재 입력값이 작은 큐의 가장 큰 값보다 크다면 큰 큐의 값과 비교
                    // 큰 큐의 가장 작은 값보다 크다면 큰 큐의 값을 뽑아 작은 큐에 넣고 현재 값을 큰 큐에 추가
                    // 큰 큐의 가장 작은 값보다 작다면 현재 값을 작은 큐에 추가
                    else{
                        int prev = big.poll();
                        putData(prev,curr);
                    }
                }
            }

            // 작은 큐의 가장 큰 값 출력
            res.add(small.peek());
        }

        StringBuilder sb = new StringBuilder();
        while(!res.isEmpty()){
            sb.append(res.poll());
            sb.append("\n");
        }
        System.out.println(sb);
    }
}

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글

관련 채용 정보