728x90

문제

 

 

접근 방식

수가 하나씩 추가될 때마다 현재까지의 수 중에서 중간값을 출력해야 하고

현재까지 부른 수가 짝수 개면 중간값은 둘 중 더 작은 수를 출력한다.

 

무식하게 생각하면 매번 수를 부를 때마다 정렬해서 중간 인덱스를 출력하는

방법을 떠올릴 수 있지만 문제의 제한 시간과 입력을 생각하면 불가능하다.

 

최소힙과 최대힙 우선순위 큐를 각각 하나씩 만들어서 특정 상황에 맞게

수를 저장하고 꺼내는 방식으로 효율적으로 풀 수 있는 문제다.

 

예를 들어 현재까지 주어진 수가 짝수 개일 때를 생각해 보면

현재 수가 이전까지의 중간값보다 작은 경우를 살펴보면 다음과 같다.

4 5 10 (11) 12 15 20	// 중간값 11
>> 6 이 입력으로 들어옴
4 5 6 (10 11) 12 15 20 // 중간값이 두개지만 더 작은 10을 선택

 

짝수일 때는 중간 값이 두 개가 될 수 있고 이 중에서 가장 작은 첫 번째 값을

골라야 하기 때문에 이 때는 최대힙에서 값을 꺼내 중간값으로 바꿔주고

이전의 중앙값을 최소힙에 다시 넣어준다.

최대힙 6 5 4
중간값 10
최소힙 11 12 15 20

 

위와 같이 최대힙, 중간값, 최소힙이 구성된다.

 

즉, 최대힙에서는 중간값보다 작은 값들을, 최소힙에서는 중간값보다 큰 값들을

정렬된 상태로 꺼낼 수 있으니 입력받은 수가 중간값보다 큰지 작은지에 따라

상황에 맞게 수를 꺼내고 저장하면 매번 정렬을 하지 않고 중간값을 알 수 있다.

 

풀이

public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();

		int n = Integer.parseInt(br.readLine());
		PriorityQueue<Integer> right = new PriorityQueue<>();
		PriorityQueue<Integer> left = new PriorityQueue<>(Collections.reverseOrder());

		int center = Integer.parseInt(br.readLine());
		sb.append(center).append("\n");

		for (int i = 2; i <= n; i++) {
			int x = Integer.parseInt(br.readLine());

			if (i % 2 == 0) {
				if (center > x) {
					left.offer(x);
					right.offer(center);
					center = left.poll();
				} else {
					right.offer(x);
				}
			} else {
				if (center <= x) {
					right.offer(x);
					left.offer(center);
					center = right.poll();
				} else {
					left.offer(x);
				}
			}

			sb.append(center).append("\n");
		}

		System.out.println(sb);
	}
}

 

'Java > Algorithms' 카테고리의 다른 글

[백준] 7662번 : 이중 우선순위 큐  (0) 2024.01.24
[백준] 1781번 : 컵라면  (1) 2024.01.22
[백준] 1715번 : 카드 정렬하기  (1) 2024.01.22
[백준] 2075번 : N번째 큰 수  (0) 2024.01.22
[백준] 1927번 : 최소 힙  (0) 2024.01.22

+ Recent posts