<포스팅 요약>
1. 문제풀러가기
https://www.acmicpc.net/problem/1655
문제 해석:
예시 입력 | 예시 출력 |
7 1 5 2 10 -99 7 5 |
1 1 2 2 2 2 5 |
> 첫째 줄에는 백준이가 외치는 정수의 개수 N이 주어진다.
> 외친 수의 개수가 짝수개라면 중간에 있는 두 수 중에서 작은 수를 말해야 한다.
1 => 중간값 : 1
1, 5=> 짝수이므로 min(1,5) =>중간값 : 1
1, 5, 2 => 정렬: 1, 2, 5 => 중간값: 2
1, 5, 2, 10 =>정렬: 1, 2, 5, 10 => 짝수이므로 min (2,5) => 중간값 : 2
1, 5, 2, 10, -99 => 정렬: -99, 1, 2, 5, 10 => 중간값: 2
1, 5, 2, 10, -99, 7 => 정렬: -99, 1, 2, 5, 7, 10 => 짝수이므로 min(2,5) => 중간값: 2
1, 5, 2, 10, -99, 7, 5 => 정렬: -99, 1, 2, 5, 5, 7, 10 => 중간값: 5
2. 문제 해결 코드
import heapq
import sys
N = int(sys.stdin.readline())
leftHeap = []
rightHeap = []
for i in range(N):
n = int(sys.stdin.readline())
if len(leftHeap) == len(rightHeap):
heapq.heappush(leftHeap, -n)
else:
heapq.heappush(rightHeap, n)
if rightHeap and rightHeap[0] < -leftHeap[0]:
right = heapq.heappop(rightHeap)
left = heapq.heappop(leftHeap)
heapq.heappush(leftHeap, -right)
heapq.heappush(rightHeap, -left)
print(-leftHeap[0])
코드 참고: https://hongcoding.tistory.com/93
(**홍코딩님의 코드를 참고하였으며, 위 링크의 포스팅에 코드 설명이 잘되어있으니
부족한 부분은 홍코딩님의 포스팅 참고 바랍니다.)
3. 로직 분석
로직 요약 :
1. leftHeap배열과 rightHeap배열이 있으면 (leftHeap과 rightHeap모두 힙정렬된 배열),
숫자를 차근차근 leftHeap과 rightHeap에 번갈아 가며 채워준다.
2. 이때 중간값은 무조건 leftHeap에서 제일 큰 숫자이다.
3. 만약 rightHeap에서 제일 작은 숫자가 leftHeap보다 작을 경우,
leftHeap의 제일 큰 숫자와 rightHeap의 제일 작은 숫자의 위치를 바꿔 준 후, leftHeap에서 제일 큰 숫자를 출력해준다.
힙정렬 사용하는 이유 :
> 다른 숫자들의 정렬은 신경쓸 필요 없이,
leftHeap에서는 가장 큰 숫자, rightHeap에서는 가장 작은 숫자만 비교하면 된다.
> 힙정렬을 사용하면, 가장 큰 숫자와 작은 숫자만 간단하게 비교할 수 있다.
> leftHeap의 경우, 최대힙(max heap)을 사용하여 leftHeap[0]에 항상 제일 큰 숫자가 위치하게 하고,
rightHeap의 경우, 최소힙(min heap)을 사용하여 rightHeap[0]에 항상 제일 작은 숫자가 위치하게 한다.
(** 아래 그림 참고하세요)
4. 코드 분석
leftHeap = []
rightHeap = []
if len(leftHeap)==len(rightHeap):
heapq.heappush(leftHeap,-n)
len(leftHeap) == 0, len(rightHeap)==0 으로 길이가 동일하므로,
첫번째 입력된 숫자를 leftHeap에 넣어준다.
** -n으로 한 이유는 파이썬에서 힙정렬은 기본적으로 최소힙(min Heap)으로 정렬된다.
최대 힙으로 정렬하려면 push할때 -(마이너스)를 붙이고,
pop하거나 출력할때 -(마이너스)를 붙여서 출력하면 된다.
여기서 rightHeap은 null이므로 아래 조건은 만족하지 않아 넘어간다.
if rightHeap and rightHeap[0] < -leftHeap[0]:
right = heapq.heappop(rightHeap)
left = heapq.heappop(leftHeap)
heapq.heappush(leftHeap, -right)
heapq.heappush(rightHeap, -left)
아래 코드로 인하여 중간값 1을 출력한다.
print(-leftHeap[0])
아래 숫자들도 위와 같은 로직으로 동작한다. ( 그림 참고하세요)
'코딩테스트 > 코딩테스트 문제' 카테고리의 다른 글
(백준) 6148번: Bookshelf 2 파이썬 풀이 (0) | 2022.11.22 |
---|---|
(백준) 9625번: BABBA 파이썬 풀이(DP풀이) (2) | 2022.11.21 |
코딩테스트: (LeetCode) 692. Top K Frequent Words 파이썬 코드/풀이 (0) | 2022.10.19 |
코딩테스트: (LeetCode) 48. Rotate Image 파이썬 코드/풀이 (2) | 2022.08.30 |
프로그래머스 - 순위 검색 Lv2 풀이/주석/자세한 설명 (0) | 2022.08.10 |
댓글