
난이도: ★★☆☆☆ • solved on: 2025-12-10

문제 유형: 자료구조, 힙(Heap), 우선순위 큐
요구사항
다음 세 가지 쿼리를 효율적으로 처리해야 한다.
1 x : 정수 x를 집합에 삽입2 x : 정수 x를 집합에서 삭제3 : 현재 집합에 있는 값들 중 최솟값을 출력힙(특히 Min Heap)을 이용해 위 연산들을 구현하는 문제이다.
자료구조
ArrayList<Integer>
완전 이진 트리(Complete Binary Tree)를 배열로 표현하기 위해 사용
인덱스 i 기준
2 * i + 12 * i + 2(i - 1) / 2알고리즘/기법
BufferedReader 사용핵심 키워드
- Min Heap으로 값 관리
- 배열 기반 힙을 직접 구현한다.
- 항상 루트 인덱스(0) 에 최솟값이 오도록 유지한다.
핵심 로직 흐름
insert(x): 1) heap 맨 뒤에 x 추가 2) 새로 들어간 인덱스에서 부모와 비교하며 위로 올림 (siftUp) deleteValue(x): 1) heap에서 값이 x인 인덱스를 선형 탐색으로 찾음 2) 찾은 위치를 마지막 원소와 교체 후 마지막 원소 제거 3) 부모보다 작은지 / 자식보다 큰지에 따라 - 위로 올릴지(siftUp) / 아래로 내릴지(siftDown) 결정 getMin(): - heap.get(0) 을 그대로 반환예외 처리 및 구현 포인트
deleteValue(x)에서 값이 존재하지 않으면 바로 반환- 삭제 시, 마지막 원소를 가져온 위치에서
- 부모보다 작으면
siftUp- 그렇지 않으면
siftDown- 입력은
BufferedReader로 한 줄씩 읽어 쿼리 타입에 따라 분기
import java.io.*;
import java.util.*;
public class Solution {
static class MinHeap {
ArrayList<Integer> heap = new ArrayList<>();
int size() {
return heap.size();
}
void swap(int i, int j) {
int tmp = heap.get(i);
heap.set(i, heap.get(j));
heap.set(j, tmp);
}
void siftUp(int i) {
while (i > 0) {
int p = (i - 1) / 2;
if (heap.get(p) <= heap.get(i)) break;
swap(p, i);
i = p;
}
}
void siftDown(int i) {
int n = heap.size();
while (true) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int smallest = i;
if (left < n && heap.get(left) < heap.get(smallest)) {
smallest = left;
}
if (right < n && heap.get(right) < heap.get(smallest)) {
smallest = right;
}
if (smallest == i) break;
swap(i, smallest);
i = smallest;
}
}
void insert(int x) {
heap.add(x);
siftUp(heap.size() - 1);
}
int getMin() {
return heap.get(0);
}
void deleteValue(int x) {
int n = heap.size();
int idx = -1;
for (int i = 0; i < n; i++) {
if (heap.get(i) == x) {
idx = i;
break;
}
}
if (idx == -1) return;
int lastIdx = n - 1;
if (idx == lastIdx) {
heap.remove(lastIdx);
return;
}
int lastVal = heap.get(lastIdx);
heap.set(idx, lastVal);
heap.remove(lastIdx);
if (idx > 0 && heap.get(idx) < heap.get((idx - 1) / 2)) {
siftUp(idx);
} else {
siftDown(idx);
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
int q = Integer.parseInt(br.readLine());
MinHeap heap = new MinHeap();
for (int i = 0; i < q; i++) {
String line = br.readLine();
while (line != null) {
String[] cmds = line.split(" ");
int type = Integer.parseInt(cmds[0]);
if (type == 1) {
int x = Integer.parseInt(cmds[1]);
heap.insert(x);
} else if (type == 2) {
int x = Integer.parseInt(cmds[1]);
heap.deleteValue(x);
} else if (type == 3) {
System.out.println(heap.getMin());
}
line = br.readLine();
}
}
}
}
삽입 insert(x)
siftUp 때문에 시간 복잡도: O(log N)최솟값 조회 getMin()
값 삭제 deleteValue(x)
siftUp 또는 siftDown: O(log N)공간 복잡도
insert, siftUp, siftDown을 직접 구현하는 구조를 잡는 데 시간이 많이 들었다.Min Heap은 “항상 루트가 최솟값”이 되도록 부모 ≤ 자식 관계를 유지하는 완전 이진 트리라는 점을 다시 한 번 정리할 수 있었다.
siftUp, siftDown은 결국
실제 코딩 테스트나 실무에서는 PriorityQueue를 쓰면 되고, 이번 풀이는 Min Heap을 직접 구현하면서 연습해본 풀이이다.
비슷한 유형 (GPT 추천)
확장 문제 (GPT 추천)