T4F1 / Algorithm

0 stars 0 forks source link

[2주차 - 3] 이중 우선순위 큐 #19

Open Jewan1120 opened 6 days ago

Jewan1120 commented 6 days ago

문제

문제 풀이 템플릿

### 시간복잡도 생각해보기
- 

### 풀이 아이디어
- 

### 의사코드 / 풀이 과정
- 
yeo-li commented 4 days ago

시간복잡도 생각해보기

풀이 아이디어

의사코드 / 풀이 과정

int T ← input()
for(1 to T) {
  tree ← TreeMap
  int k ← input()
  for(1 to k) {
    String op ← input()
    int number ← input()
    if(op = "I") {
      tree.put(number, number.getOrDefault(number, 0) + 1)
    } else if(op = "D") {
      if(tree.isEmpty()) {
        continue
      }
      if(number = 1) {
        int key ← tree.lastKey()
      } else {
        int key ← tree.firstKey()
      }
      if(tree.get(key) > 1) {
        tree.put(key, tree.get(key) - 1)
      } else {
        tree.remove(key);
      }
    }
  }
  print(result) // 적절한 답 출력
}
rladmstn commented 4 days ago

시간복잡도 생각해보기

풀이 아이디어

의사코드 / 풀이 과정

TreeMap<Integer, Integer> map : <숫자, 빈도수> 구조로 저장하는 map

매 테스트 케이스마다 반복

입력받은 k번 만큼 반복

if(커맨드 == "I"){
    map.put(숫자, map.getOrDefault(숫자,0)+1));
} else { // "D" 입력
    map이 비어있으면 continue;

    int val = 숫자 == 1 ? map.lastKey() : map.firstKey();
    if(map에서 val의 빈도수를 -1 했을 때 결과가 1인 경우){ // 모두 제거됨 의미
          map.remove(val);
    }
}
Jewan1120 commented 3 days ago

시간복잡도 생각해보기

유형 우선순위 큐 (PriorityQueue) 트리맵 (TreeMap)
삽입 O(log N) O(log N)
조회 O(1) (최상위 요소) O(log N)
삭제 O(log N) O(log N)

풀이 아이디어

위: 트리맵 / 아래: 우선순위 큐

image

의사코드 / 풀이 과정

// 출력 if(tm.isEmpty()) // "EMPTY" else // 조건에 맞게 출력



> -2^31이상 2^31미만인 정수라서 오버플로우남... 함정 😿
yereumi commented 3 days ago

시간복잡도 생각해보기

풀이 아이디어

의사코드 / 풀이 과정

int t <- input()
for (int i = 0 -> t - 1) {
    TreeMap<Integer, Integer> tm = new TreeMap<>()
    int n <- input()
    for (int j = 0 -> n - 1) {
        String f <- input()
        if (f == "I") {
            tm.put(num, tm.getOrDefault(num, 0) + 1)
        } else if (f == "D") {
            if (!tm.isEmpty() && num == 1) {
                int removeNum = tm.lastKey()
                if (tm.get(removeNum) == 1) tm.remove(removeNum)
                else tm.put(removeNum, tm.get(removeNum) - 1)
            }
            if (!tm.isEmpty() && num == -1) {
                int removeNum = tm.firstKey()
                if (tm.get(removeNum) == 1) tm.remove(removeNum)
                else tm.put(removeNum, tm.get(removeNum) - 1)
            }
        }
    }
}
if (tm.isEmpty()) 
    print("EMPTY\n")
} else {
    print(tm.lastKey() + " " + tm.firstKey() + "\n")
}

틀린코드

1. 첫 번째

우선순위큐 문제라 PriorityQueue 2개를 각각 오름차순, 내림차순으로 선언해서 해줬는데 시간초과가 났다. 두 개의 PriorityQueueremove 연산을 해서 시간이 오래 걸리는 것 같다. $\rightarrow$ TreeMap으로 해결했다.

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

public class Main {

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PriorityQueue<Integer> ascendPq = new PriorityQueue<>();
        PriorityQueue<Integer> descendPq = new PriorityQueue<>(Collections.reverseOrder());
        int t = Integer.parseInt(br.readLine());
        for (int i = 0; i < t; i++) {
            int n = Integer.parseInt(br.readLine());
            for (int j = 0; j < n; j++) {
                StringTokenizer st = new StringTokenizer(br.readLine());
                String f = st.nextToken();
                if (f.equals("I")) {
                    int num = Integer.parseInt(st.nextToken());
                    ascendPq.add(num);
                    descendPq.add(num);
                } else if (f.equals("D")) {
                    int num = Integer.parseInt(st.nextToken());
                    if (!descendPq.isEmpty() &&  num == 1) {
                        int remove = descendPq.remove();
                        ascendPq.remove(remove);
                    }
                    if (!ascendPq.isEmpty() && num == -1) {
                        int remove = ascendPq.remove();
                        descendPq.remove(remove);
                    }
                }   
            }
            if (ascendPq.isEmpty() || descendPq.isEmpty()) {
                System.out.println("EMPTY");
            } else {
                System.out.println(descendPq.peek() + " " + ascendPq.peek());
            }
        }
    }
}

2. 두 번째

$\rightarrow$ 내림차순으로 선언할 때, @Override를 하는 방식으로 변경

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

public class Main {

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int t = Integer.parseInt(br.readLine());
        for (int i = 0; i < t; i++) {
            TreeMap<Integer, Integer> tm = new TreeMap<>((o1, o2) -> o1 - o2); // 여기서 오류 발생, 중복 값을 허용하므로 에러나는 것으로 추정
            int n = Integer.parseInt(br.readLine());
            for (int j = 0; j < n; j++) {
                StringTokenizer st = new StringTokenizer(br.readLine());
                String f = st.nextToken();
                if (f.equals("I")) {
                    int num = Integer.parseInt(st.nextToken());
                    tm.put(num, tm.getOrDefault(num, 0) + 1);
                } else if (f.equals("D")) {
                    int num = Integer.parseInt(st.nextToken());
                    if (!tm.isEmpty() && num == 1) {
                        int remove = tm.lastKey();
                        if (tm.get(remove) == 1) tm.remove(remove);
                        else tm.put(remove, tm.get(remove) - 1);
                    }
                    if (!tm.isEmpty() && num == -1) {
                        int remove = tm.firstKey();
                        if (tm.get(remove) == 1) tm.remove(remove);
                        else tm.put(remove, tm.get(remove) - 1);
                    }
                }
            }
            if (tm.isEmpty()) {
                System.out.println("EMPTY");
            } else {
                System.out.println(tm.lastKey() + " " + tm.firstKey());
            }
        }
    }
}
chaerish commented 2 days ago

시간복잡도 생각해보기

-최대로 10의 6승이므로 O(NlogN) 까지만 가능함.

- deque 사용해야하나  -> 우선순위 queue 구현하기 어려워보임
- 우선순위 큐 두개 -> 두개 큐의 원소가 달라서 삽입 삭제가 자주 일어날경우 키가 꼬임 
- 그래서 우선순위 큐에서 hashMap을 사용해서 boolean 값으로 표현하려고 했는데, 생각해보니깐 중복이 가능하니 map.remove() 한후에 할걸 생각도 든다...
- 다시 풀어보려고 했는데 큐 동기화가 빡세서 안할거다 
### 의사코드 / 풀이 과정
```java
for(int i = 0; i<K;i++) {
        StringTokenizer st = new StringTokenizer(br.readLine());
        String m = st.nextToken();
        int num = Integer.parseInt(st.nextToken());
        if(m.equals("I")) {
            map.put(num, map.getOrDefault(num, 0)+1);
        }else if(map.size() == 0){
            continue;
        }
        else if(m.equals("D") && num == -1){ //최솟값삭제
            remove(map.firstKey());
        }else if(m.equals("D") && num == 1) { // 최댓값삭제
            remove(map.lastKey());
        }
    }
    if(map.size()==0) {
        sb.append("EMPTY").append("\n");
    }else {
        int min = map.firstKey();
        int max = map.lastKey();
        sb.append(max).append(" ").append(min).append("\n");    
    }
}