코딩테스트/BOJ

[BOJ] 7662 이중 우선순위 큐 - JAVA

5월._. 2023. 6. 16.
728x90

1. 문제

 

7662번: 이중 우선순위 큐

입력 데이터는 표준입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터의 첫째 줄에는 Q에 적

www.acmicpc.net

이중 우선순위 큐(dual priority queue)는 전형적인 우선순위 큐처럼 데이터를 삽입, 삭제할 수 있는 자료 구조이다. 전형적인 큐와의 차이점은 데이터를 삭제할 때 연산(operation) 명령에 따라 우선순위가 가장 높은 데이터 또는 가장 낮은 데이터 중 하나를 삭제하는 점이다. 이중 우선순위 큐를 위해선 두 가지 연산이 사용되는데, 하나는 데이터를 삽입하는 연산이고 다른 하나는 데이터를 삭제하는 연산이다. 데이터를 삭제하는 연산은 또 두 가지로 구분되는데 하나는 우선순위가 가장 높은 것을 삭제하기 위한 것이고 다른 하나는 우선순위가 가장 낮은 것을 삭제하기 위한 것이다. 

정수만 저장하는 이중 우선순위 큐 Q가 있다고 가정하자. Q에 저장된 각 정수의 값 자체를 우선순위라고 간주하자. 

Q에 적용될 일련의 연산이 주어질 때 이를 처리한 후 최종적으로 Q에 저장된 데이터 중 최댓값과 최솟값을 출력하는 프로그램을 작성하라.


2. 풀이

TreeMap은 내부적으로 정렬이 되는 Map 구현체다. 여기서 TreeMap만 가지고 있는 firstKey(), lastKey()를 이용하려면 평소처럼 Map 타입에 TreeMap객체를 넣으면 안된다. TreeMap을 생성할 때 정렬순서를 지정할 수 있지만 key의 타입이 Integer라 굳이 지정하지 않았다.

 

입력이 "I"라면 map에 그대로 put한다. 단, 이미 있는 숫자라면 value값에 +1해서 넣는다.

입력이 "D"라면 다음의 절차를 따른다.

1. map 사이즈가 0이라면 아무것도 하지 않는다.

2. num이 양수라면 가장 큰 숫자를 삭제한다. map의 lastKey를 del에 저장한다. 

3. num이 음수라면 가장 작은 숫자를 삭제한다. map의 firstKey를 del에 저장한다.

4. map.get(del)이 몇 갠지 cnt에 저장한다. 만약 cnt=1이라면 map에서 del 을 아예 삭제한다.

5. cnt>1이라면 map.put(del,cnt-1)을 사용해서 갱신한다.

 

명령 입력이 모두 끝난 후 map의 사이즈가 0이라면 EMPTY를, 1이상이라면 map의 lastKey와 firstKey를 sb에 더한다.

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

public class BOJ_7662_이중우선순위큐 {
   public static void main(String[] args) throws IOException {
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      int T = Integer.parseInt(in.readLine());
      StringBuilder sb = new StringBuilder();
      StringTokenizer st;

      for(int tc=0;tc<T;tc++){
         int K = Integer.parseInt(in.readLine());
         TreeMap<Integer, Integer> map = new TreeMap<>();
         for(int k=0;k<K;k++){
            st = new StringTokenizer(in.readLine());
            String command = st.nextToken();
            int num = Integer.parseInt(st.nextToken());
            switch (command){
               case "I":
                  map.put(num,map.getOrDefault(num,0)+1);
                  break;
               case "D":
                  if(map.size()==0) break;
                  int del = num>0? map.lastKey():map.firstKey();
                  int cnt = map.get(del);
                  if(cnt==1) map.remove(del);
                  else map.put(del,cnt-1);
                  break;
            }
         }

         if(map.size()==0) sb.append("EMPTY\n");
         else sb.append(map.lastKey()).append(" ").append(map.firstKey()).append('\n');
      }

      System.out.print(sb);
   }
}

3. 결과

우선순위 큐 두 개를 사용해서 min, max를 구하고 map을 활용해서 유효한 숫자인지 검증하는 방법을 썼다. 다른 사람보다 시간이 너무 많이 걸려서 다른 방법을 찾다가 TreeMap의 firstKey, lastKey를 발견했다.

이 문제에서는 TreeMap을 쓰는게 더 올바른 방향 같다.

'코딩테스트 > BOJ' 카테고리의 다른 글

[BOJ] 16928 뱀과 사다리 게임 - JAVA  (0) 2023.06.18
[BOJ] 9019 DSLR - JAVA  (0) 2023.06.17
[BOJ] 1107 리모컨 - JAVA  (0) 2023.06.15
[BOJ] 14940 쉬운 최단거리 - JAVA  (0) 2023.06.14
[BOJ] 12852 1로 만들기 2 - JAVA  (0) 2023.06.13

댓글