문제 설명
이중 우선순위 큐는 다음 연산을 할 수 있는 자료구조를 말합니다.
이중 우선순위 큐가 할 연산 operations가 매개변수로 주어질 때, 모든 연산을 처리한 후 큐가 비어있으면 [0,0] 비어있지 않으면 [최댓값, 최솟값]을 return 하도록 solution 함수를 구현해주세요.
제한사항- operations는 길이가 1 이상 1,000,000 이하인 문자열 배열입니다.
- operations의 원소는 큐가 수행할 연산을 나타냅니다.
- 원소는 “명령어 데이터” 형식으로 주어집니다.- 최댓값/최솟값을 삭제하는 연산에서 최댓값/최솟값이 둘 이상인 경우, 하나만 삭제합니다.
- 빈 큐에 데이터를 삭제하라는 연산이 주어질 경우, 해당 연산은 무시합니다.
입출력 예 #1
- 16과 -5643을 삽입합니다.
- 최솟값을 삭제합니다. -5643이 삭제되고 16이 남아있습니다.
- 최댓값을 삭제합니다. 16이 삭제되고 이중 우선순위 큐는 비어있습니다.
- 우선순위 큐가 비어있으므로 최댓값 삭제 연산이 무시됩니다.
- 123을 삽입합니다.
- 최솟값을 삭제합니다. 123이 삭제되고 이중 우선순위 큐는 비어있습니다.
따라서 [0, 0]을 반환합니다.
입출력 예 #2
- -45와 653을 삽입후 최댓값(653)을 삭제합니다. -45가 남아있습니다.
- -642, 45, 97을 삽입 후 최댓값(97), 최솟값(-642)을 삭제합니다. -45와 45가 남아있습니다.
- 333을 삽입합니다.
이중 우선순위 큐에 -45, 45, 333이 남아있으므로, [333, -45]를 반환합니다.
<코드>
import heapq
def solution(operations):
min_heap = []
max_heap = []
entry_finder = {} # 현재 힙에 있는 유효한 항목을 추적
for operation in operations:
command, num = operation.split()
num = int(num)
if command == 'I':
heapq.heappush(min_heap, num)
heapq.heappush(max_heap, -num)
if num in entry_finder:
entry_finder[num] += 1
else:
entry_finder[num] = 1
elif command == 'D':
if num == 1 and max_heap:
# 최댓값 삭제
while max_heap and entry_finder.get(-max_heap[0], 0) == 0:
heapq.heappop(max_heap)
if max_heap:
max_val = -heapq.heappop(max_heap)
entry_finder[max_val] -= 1
if entry_finder[max_val] == 0:
del entry_finder[max_val]
elif num == -1 and min_heap:
# 최솟값 삭제
while min_heap and entry_finder.get(min_heap[0], 0) == 0:
heapq.heappop(min_heap)
if min_heap:
min_val = heapq.heappop(min_heap)
entry_finder[min_val] -= 1
if entry_finder[min_val] == 0:
del entry_finder[min_val]
# 최종 결과 계산
while min_heap and entry_finder.get(min_heap[0], 0) == 0:
heapq.heappop(min_heap)
while max_heap and entry_finder.get(-max_heap[0], 0) == 0:
heapq.heappop(max_heap)
if not min_heap or not max_heap:
return [0, 0]
min_val = min_heap[0]
max_val = -max_heap[0]
return [max_val, min_val]
<풀이과정>
- min_heap:최소 힙(최솟값 검색)
- max_heap: 최대 힙 (값을 음수로 저장하여 최소 힙처럼 동작하도록 함)
- entry_finder: 힙에 있는 항목을 추적하는 딕셔너리로, 각 항목의 개수를 저장
- 리스트의 값을 command와 숫자로 분리
- 주어진 숫자를 min_heap과 max_heap에 삽입(max_heap에는 음수로 변환하여 삽입)
- entry_finder에서 해당 숫자의 개수를 증가시키거나 새로 추가
- D 1: 최대 힙에서 최댓값 삭제, entry_finder에서 유효한 항목만 처리
- D -1: 최소 힙에서 최솟값 삭제, entry_finder에서 유효한 항목만 처리
- 힙에서 유효하지 않은 항목을 제거 후 두 힙이 비어 있는지 확인
* entry_finder의 역할
- 항목의 직접 삭제는 힙의 규칙을 깨뜨릴 수 있으며, 이를 조정하려면 전체 힙을 재구성해야 하기에 상태를 추적해서 이후에 삭제하는 것이 효율적
- 지연 삭제:
- 항목을 삽입할 때, 최소 힙과 최대 힙에 추가
- 항목을 삭제할 때는 항목이 실제로 힙에서 제거되지 않고, entry_finder에서 카운트를 감소시킨 후 실제 삭제는 힙에서 유효한 항목만 확인할 때 수행
- 유효하지 않은 항목 제거:
- 최솟값 또는 최댓값을 삭제할 때, 힙에서 유효하지 않은 항목을 건너뛰고, 유효한 항목만 삭제
- 힙에서 유효하지 않은 항목을 제거하여 최종적으로 유효한 값만 남도록
'2024 코딩테스트 스터디' 카테고리의 다른 글
[9주_5일차] 프로그래머스-전화번호 목록(Python) (0) | 2024.08.03 |
---|---|
[9주_4일차] 프로그래머스-완주하지 못한 선수(Python) (0) | 2024.08.02 |
[9주_2일차] 프로그래머스-디스크 컨트롤러(Python) (0) | 2024.07.31 |
[9주_1일차] 프로그래머스-더 맵게(Python) (0) | 2024.07.30 |
[8주_7일차] 백준-9095 1,2,3 더하기(Python) (0) | 2024.07.29 |