힙 자료구조를 사용해야 하는 최대 힙 문제이다
문제의 내용은 2가지 연산을 지원하는데
0인 경우엔 최대힙에서 가장 윗부분 가장 큰 수를 삭제 후 출력
0이 아닌 경우엔 최대힙에 삽입하는 것이다.
힙 정렬을 배웠지만
힙 정렬은 삽입 없이 삭제 후 다시 힙으로 만들어 주는 과정을 반복하지
삽입과 삭제를 따로 구현하지 않아서
힙에서 삽입과 삭제를 따로 구현하려니까
생각대로 잘 안됐다.
코드를 천천히 살펴보면서 꼭 복습해보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Q11279 {
public static int [] heap = new int[100001];
public static int size = 0;
public static StringBuilder sb = new StringBuilder();
public static void swap(int x, int y) {
int temp = heap[x];
heap[x] = heap[y];
heap[y] = temp;
}
public static void push(int x) {
heap[++size] = x;
//삽입한 것 부터 힙인지 확인, 힙이아니면 계속 부모노드로 올라가고 힙이면 break
for(int i=size; i>1; i/=2) {
if(heap[i/2] < heap[i]) {
swap(i/2, i);
} else {
break;
}
}
}
public static void pop() {
heap[1] = heap[size];
heap[size--] = 0;
for(int i=1; i*2<=size;) { //삭제 후 1에서 부터 힙으로 만들어주는 과정
if(heap[i] > heap[i*2] && heap[i] > heap[i*2+1]) {
break;
}else if(heap[i*2] > heap[i*2+1]) {
swap(i, i*2);
i = i*2;
} else {
swap(i, i*2+1);
i = i*2+1;
}
}
}
public static void main(String[] args) throws IOException{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(reader.readLine());
for(int i=0; i<n; i++) {
int k = Integer.parseInt(reader.readLine());
if(k==0) {
if(size == 0) {
} else {
pop();
}
} else {
push(k);
}
}
System.out.print(sb.toString());
}
}
|
이 문제를 힙을 구현하지 않고도 해결할 수 있는 방법이 있는데
바로 PriorityQueue(우선순위 큐)이다.
PriorityQueue는 삭제 연산을 했을 때 우선순위가 가장 높은 것을 우선으로 삭제한다.
자바에서는 라이브러리에 있는 우선순위 큐를 특별한 설정 없이 사용했을 때
최소 힙처럼 최솟값을 우선으로 삭제한다.
이 문제에서는 최댓값을 삭제 후 출력해줘야 하므로
우선순위 큐에 삽입시에 -1을 곱해서 음수 형태로 삽입시켜줌으로써
최댓값이 우선순위가 가장 높게 해주고
삭제 시에 삭제된 값에 -1을 곱해서 출력하면 양수 형태로 출력되게 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
import java.util.Queue;
public class Q11279_ver2 {
public static void main(String[] args) throws IOException{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(reader.readLine());
Queue<Integer> q = new PriorityQueue<>();
StringBuilder sb = new StringBuilder();
for(int i=0; i<n; i++) {
int k = Integer.parseInt(reader.readLine());
if(k==0) {
if(q.isEmpty()) {
} else {
//출력할 땐 다시 -1을 곱해서 양수로
}
} else {
//최댓값을 삭제해야 하므로 삽입 시 -1을 곱해준다.
q.add(k*-1);
}
}
System.out.print(sb.toString());
}
}
|
PriorityQueue를 사용한 코드가 훨씬 깔끔하다.
PriorityQueue도 힙 자료구조를 사용하여 구현한 것이기 때문에
시간 복잡도는 최대 힙이나 우선순위 큐나 둘 다 삽입, 삭제 시에 O(logn)의 시간 복잡도를 가진다.
하지만 두 코드를 전부 백준에서 채점하면 최대 힙을 구현한 코드가 좀 더 빠른 실행 시간을 가진다.
'Algorithm' 카테고리의 다른 글
백준 2252 줄 세우기 Java (0) | 2019.08.12 |
---|---|
백준 9375 패션왕 신해빈 Java (0) | 2019.08.09 |
백준 14888 연산자 끼워넣기 Java (0) | 2019.08.07 |
백준 2606 바이러스 Java (0) | 2019.08.07 |
백준 1717 집합의 표현 Java (0) | 2019.08.07 |