728x90
반응형
문제 살펴보기!!
문제 링크 : https://www.acmicpc.net/problem/7662
반응형
솔루션 살펴보기!!
import sys
import heapq
from collections import defaultdict
def input():
return sys.stdin.readline().rstrip()
def process_test_case():
max_heap = [] # 최대값을 위한 최대 힙
min_heap = [] # 최소값을 위한 최소 힙
element_count = defaultdict(int) # 각 숫자의 삽입 횟수를 기록
total_elements = 0 # 현재 유효한 원소의 개수
for _ in range(int(input())):
operation, number = input().split()
if operation == 'I': # 숫자 삽입
number = int(number)
heapq.heappush(max_heap, -number) # 최대값 힙 (부호 변경하여 최대 힙으로 사용)
heapq.heappush(min_heap, number) # 최소값 힙
element_count[number] += 1 # 삽입된 숫자의 개수 증가
total_elements += 1 # 총 원소 개수 증가
elif total_elements > 0: # 삭제 연산 (총 원소가 있을 때만)
if number == '1': # 최대값 삭제
# 유효한 최대값을 찾을 때까지 반복
while max_heap:
max_val = -heapq.heappop(max_heap)
if element_count[max_val] > 0:
element_count[max_val] -= 1 # 해당 값 개수 감소
total_elements -= 1 # 유효한 원소 개수 감소
break
else: # 최소값 삭제
# 유효한 최소값을 찾을 때까지 반복
while min_heap:
min_val = heapq.heappop(min_heap)
if element_count[min_val] > 0:
element_count[min_val] -= 1 # 해당 값 개수 감소
total_elements -= 1 # 유효한 원소 개수 감소
break
# 남아있는 유효한 원소가 있을 경우 최대값과 최소값 출력
if total_elements > 0:
# 유효한 최대값 찾기
while max_heap:
max_val = -heapq.heappop(max_heap)
if element_count[max_val] > 0:
break
# 유효한 최소값 찾기
while min_heap:
min_val = heapq.heappop(min_heap)
if element_count[min_val] > 0:
break
print(max_val, min_val) # 최대값과 최소값 출력
else:
print('EMPTY') # 남아있는 원소가 없을 경우 EMPTY 출력
# 테스트 케이스 개수만큼 처리
for _ in range(int(input())):
process_test_case()
코드 흐름 및 풀이 전략 설명
이 코드는 이중 우선순위 큐 문제를 해결하는 방식으로, 두 개의 우선순위 큐(최대 힙과 최소 힙)를 사용하여 주어진 연산에 맞게 최대값과 최소값을 효율적으로 처리합니다. 각 연산에 대해 삽입과 삭제가 빈번히 발생하므로, 힙 자료구조를 통해 시간 복잡도를 최적화했습니다.
주요 흐름
- 입력 처리 및 초기화:
- sys.stdin.readline()으로 입력을 빠르게 처리합니다. 입력으로 주어진 테스트 케이스의 개수와 각 테스트 케이스에서의 연산을 처리합니다.
- 두 개의 힙을 사용:
- max_heap: 최대값을 빠르게 찾기 위한 힙 (부호를 반대로 하여 최대 힙처럼 사용)
- min_heap: 최소값을 빠르게 찾기 위한 힙
- defaultdict(int)로 원소의 삽입 및 삭제 여부를 관리합니다. 삽입된 숫자가 아직 유효한지(즉, 삭제되지 않은 상태인지)를 추적하기 위함입니다.
- 삽입 연산 (I):
- heapq를 사용해 숫자를 두 힙에 동시에 삽입합니다:
- max_heap: 부호를 반대로 하여 숫자를 넣어 최대 힙처럼 동작시킴.
- min_heap: 원래 값을 넣어 최소 힙처럼 동작.
- 삽입된 숫자의 개수를 element_count에서 기록하여, 숫자의 유효성을 관리합니다.
- heapq를 사용해 숫자를 두 힙에 동시에 삽입합니다:
- 삭제 연산 (D):
- 최대값 삭제 (D 1): max_heap에서 최대값을 꺼내고, 그 값이 실제로 유효한지 확인합니다. 삭제된 값이 다시 사용되지 않도록 element_count에서 해당 숫자의 카운트를 감소시킵니다.
- 최소값 삭제 (D -1): min_heap에서 최소값을 꺼내고, 마찬가지로 유효한 값인지 확인한 후 삭제 처리합니다.
- 힙에 남아 있는 값이 삭제된 값일 수 있기 때문에, 실제로 유효한 값이 나올 때까지 반복해서 꺼내는 방식을 사용합니다.
- 결과 출력:
- 모든 연산이 끝난 후, 남아 있는 숫자들 중에서 유효한 최대값과 최소값을 각각 찾아서 출력합니다.
- 만약 유효한 숫자가 없다면, "EMPTY"를 출력합니다.
각 주요 부분에 대한 설명
입력 처리 및 자료구조 초기화
max_heap = []
min_heap = []
element_count = defaultdict(int)
total_elements = 0
- max_heap과 min_heap은 각각 최대값과 최소값을 빠르게 찾기 위해 사용됩니다.
- element_count는 숫자의 삽입과 삭제 여부를 추적하여, 힙에서 삭제된 숫자가 힙에 남아있을 수 있는 상황을 처리합니다.
삽입 연산 (Insert operation)
heapq.heappush(max_heap, -number)
heapq.heappush(min_heap, number)
element_count[number] += 1
total_elements += 1
- 삽입 시, 숫자는 min_heap에 그대로, max_heap에는 부호를 반대로 해서 삽입합니다. 이 방식으로 최대값을 max_heap에서 쉽게 찾을 수 있습니다.
- element_count[number]는 삽입된 숫자의 개수를 증가시킵니다.
삭제 연산 (Delete operation)
if number == '1': # 최대값 삭제
while max_heap:
max_val = -heapq.heappop(max_heap)
if element_count[max_val] > 0:
element_count[max_val] -= 1
total_elements -= 1
break
- max_heap에서 최대값을 뽑아내고, 그 값이 유효한지 확인합니다. 유효하지 않다면 계속해서 값을 꺼내 유효한 값이 나올 때까지 반복합니다.
- 유효한 값을 찾으면, 그 숫자의 개수를 element_count에서 감소시키고, 총 원소 개수도 감소시킵니다.
최종 결과 출력
if total_elements > 0:
while max_heap:
max_val = -heapq.heappop(max_heap)
if element_count[max_val] > 0:
break
while min_heap:
min_val = heapq.heappop(min_heap)
if element_count[min_val] > 0:
break
print(max_val, min_val)
else:
print('EMPTY')
- 모든 연산이 끝난 후, 남아있는 유효한 최대값과 최소값을 각각 찾아 출력합니다. 힙에서 유효하지 않은 값들이 남아있을 수 있기 때문에, 유효한 값이 나올 때까지 힙에서 값을 꺼냅니다.
코딩 인터뷰 시 답변할 수 있는 주요 개념
- 이중 우선순위 큐 (Dual Priority Queue):
- 이중 우선순위 큐는 최대값과 최소값을 모두 효율적으로 처리할 수 있어야 합니다. 이 문제에서는 heapq 모듈을 사용해 두 개의 힙을 구성하고, 하나는 최대값을, 다른 하나는 최소값을 관리하는 방식으로 구현했습니다.
- Heap 자료구조:
- Python에서 heapq는 최소 힙을 제공하는데, 이를 활용해 효율적인 삽입 및 삭제 연산을 구현할 수 있습니다. 최대 힙이 필요할 때는 값을 -1 곱해서 힙에 넣는 방법을 사용해 최대 힙처럼 동작하게 할 수 있습니다.
- 힙을 사용하면 삽입 및 삭제 연산의 시간 복잡도는 O(logN)O(\log N)입니다.
- Lazy Deletion (지연 삭제):
- 삭제 연산에서 실제로 값이 삭제되었는지 확인하기 위해 힙에 있는 값이 유효한지 확인하는 방식입니다. 값이 힙에 남아있지만 실제로는 삭제된 경우를 처리하기 위해 element_count를 사용해 유효성 여부를 추적합니다.
- 지연 삭제를 통해 힙에서 유효하지 않은 값을 제거하면서도 성능을 크게 저하시키지 않습니다.
- defaultdict를 사용한 값 추적:
- defaultdict(int)를 사용해 삽입된 숫자의 카운트를 관리하며, 이를 통해 각 숫자가 몇 번 삽입되었고 몇 번 삭제되었는지 쉽게 추적할 수 있습니다.
- 이 방식은 숫자의 유효성을 확인하는 데 중요한 역할을 하며, 이를 통해 힙에서 삭제된 값을 효율적으로 처리할 수 있습니다.
- 입출력 최적화:
- sys.stdin.readline()을 사용해 입력을 빠르게 처리하고, 큰 입력을 효과적으로 처리할 수 있도록 성능을 최적화했습니다.
728x90
반응형
'알고리즘' 카테고리의 다른 글
백준 알고리즘 문제 풀이 가이드: 코딩 면접 대비 완벽 준비-1068 트리 편 (python) (0) | 2024.09.25 |
---|---|
백준 알고리즘 문제 풀이 가이드: 코딩 면접 대비 완벽 준비-21939 문제 추천 시스템 Version 1 편 (python) (0) | 2024.09.23 |
백준 알고리즘 문제 풀이 가이드: 코딩 면접 대비 완벽 준비-14425 문자열 집합 편 (python) (0) | 2024.09.20 |
백준 알고리즘 문제 풀이 가이드: 코딩 면접 대비 완벽 준비-1620 나는야 포켓몬 마스터 이다솜 편 (python) (0) | 2024.09.13 |
백준 알고리즘 문제 풀이 가이드: 코딩 면접 대비 완벽 준비-2800 괄호 제거 편 (python) (0) | 2024.09.12 |