이번 강좌에서는 절댓값 힙을 구현하는 알고리즘 문제를 다루고자 합니다. 이 문제는 C++ 프로그래밍에서 자주 출제되는 유형 중 하나로, 우선순위 큐(Priority Queue)를 사용하여 해결할 수 있습니다. 절댓값 힙은 특정 숫자의 절댓값을 기준으로 정렬하는 자료구조입니다.
문제 설명
절댓값 힙은 다음과 같은 연산을 지원합니다:
- 정수 x를 힙에 삽입합니다.
- 가장 작은 절댓값을 가진 정수를 힙에서 제거하고 반환합니다. 만약 절댓값이 같은 수가 여러 개일 경우, 더 작은 값을 반환합니다. 만약 힙이 비어있다면 0을 반환합니다.
입력
첫 번째 줄에 연산의 개수 N
(1 ≤ N
≤ 100,000)이 주어집니다. 다음 N
개의 줄에는 실행할 연산이 주어집니다. 연산은 다음 두 가지로 나뉩니다:
삽입
:0
x
(−109 ≤x
≤ 109) 형태로 주어지며, 절댓값 힙에x
를 삽입합니다.삭제
:0
형태로 주어지며, 절댓값 힙에서 가장 작은 절댓값을 가진 정수를 제거하고 반환합니다.
출력
삭제 연산의 결과를 한 줄에 하나씩 출력합니다.
예제 입력
10 1 -1 0 1 0 -1 0 0 0 0
예제 출력
-1 1 0 0 0
문제 접근
이 문제를 해결하기 위해 우선순위 큐를 사용할 것입니다. C++ 표준 라이브러리에서는 std::priority_queue
를 제공하는데, 기본적으로 최대 힙으로 작동합니다. 하지만 우리는 절댓값을 기준으로 최소 힙을 만들어야 합니다. 따라서 std::priority_queue
를 커스터마이징하여 이를 구현할 것입니다.
힙 구현
절댓값 힙을 구현하기 위해 다음과 같은 비교 함수를 정의할 것입니다:
struct Compare { bool operator()(int a, int b) { if (abs(a) == abs(b)) { return a > b; // 절댓값이 같으면 더 작은 값을 선택 } return abs(a) > abs(b); // 절댓값 기준으로 선택 } };
위와 같은 비교 함수를 기준으로 우선순위 큐를 정의하고, 삽입 연산 및 삭제 연산을 수행할 수 있습니다.
C++ 코드 구현
#include#include #include #include using namespace std; // 비교 연산자 정의 struct Compare { bool operator()(int a, int b) { if (abs(a) == abs(b)) { return a > b; // 절댓값이 같으면 더 작은 값을 선택 } return abs(a) > abs(b); // 절댓값을 기준으로 선택 } }; int main() { int N; cin >> N; priority_queue , Compare> pq; // 커스터마이징된 우선순위 큐 for (int i = 0; i < N; i++) { int x; cin >> x; if (x == 0) { // 삭제 연산 if (pq.empty()) { cout << 0 << endl; // 비어있을 경우 0 출력 } else { cout << pq.top() << endl; // 절댓값 힙에서 가장 작은 값을 출력 pq.pop(); // 힙에서 삭제 } } else { // 삽입 연산 pq.push(x); // 힙에 값 추가 } } return 0; }
코드 설명
위 C++ 코드는 절댓값 힙을 구현합니다:
priority_queue
에서Compare
구조체를 사용하여 우선순위를 설정하고 있습니다.main
함수 내에서 입력을 읽고,0
입력 시에는 힙에서 데이터를 삭제하고 출력하며, 다른 숫자는 힙에 삽입합니다.
시간 복잡도 분석
이 알고리즘의 시간 복잡도는 다음과 같습니다:
- 삽입 연산: O(log N)
- 삭제 연산: O(log N)
따라서 총 N
개의 연산을 수행할 경우, 전체 시간 복잡도는 O(N log N)입니다.
결론
이번 강좌에서는 C++로 절댓값 힙을 구현하는 방법을 배우고, 우선순위 큐를 활용하여 효율적으로 데이터를 관리하는 방법을 알아보았습니다. 이 문제는 코딩 테스트에서 중요한 개념 중 하나이므로, 연습을 통해 이해를 깊이 있는 것으로 발전시키기를 바랍니다.