힙?

힙은 최댓값 및 최솟값을 찾아내는 연산을 빠르게 하기 위해 고안된 완전이진트리를 기본으로 한 자료구조 입니다
- 출처 위키백과

힙구조를 한번 봅시다.
힙은 기본적으로 완전이진트리 입니다.
자식노드는 왼쪽노드부터 차곡차곡 빠진 노드 없이 쌓아간다는게 특징이지요.
그렇지만 이진탐색트리와는 차이가 있습니다.
힙은 부모노드가 자식노드보다 크거나 (max heap), 작아야한다(min heap)라는 규칙이 있지만, 왼쪽 자식과 오른쪽 자식간의 차이는 없습니다.
그러나 이진 탐색트리는 부모노드의 값보다 작은 값을 가지면 왼쪽 자식, 큰 값을 가지면 오른쪽 자식으로 가기 떄문에 힙과는 사용에서 차이가 있습니다.
힙의 삽입
힙의 삽입은 간단합니다. 맨 마지막 노드 다음에 값을 넣으면 되거든요.
그 뒤에, 넣은 노드의 부모와 자신을 비교해서 자식노드가 크다면 ( 최대힙의 경우) 부모노드와 자식노드의 위치를 바꿔줍니다. 이 과정을 루트노드까지 반복해주면 삽입이 완료됩니다.
힙의 삭제
힙은 제일 첫 원소만 삭제할 수 있습니다. 루트 노드를 삭제하는 법을 알아보면,
제일 먼저 루트노드와 마지막 노드의 자리를 바꾼다 ( 마지막 노드가 루트노드가 됨 )
그 이후 루트노드에서 양쪽 자식 중에 큰 값 (최
대힙의 경우)과 자신의 위치를 바꾸는 과정을 리프노드까지 반복합니다.




힙의 원소 삭제는 트리의 높이 만큼의 시간복잡도를 가지니
O(log N)이라고 할 수 있습니다.
Maximum Product of Two Elements in an Array 배열의 최대 곱
https://leetcode.com/problems/maximum-product-of-two-elements-in-an-array
Maximum Product of Two Elements in an Array - LeetCode
Can you solve this real interview question? Maximum Product of Two Elements in an Array - Given the array of integers nums, you will choose two different indices i and j of that array. Return the maximum value of (nums[i]-1)*(nums[j]-1). Example 1: Inpu
leetcode.com
list에서 제공하는 sort기능을 쓸 수도 있지만, 힙을 연습하는 의미로 풀어보았습니다.
파이썬 heapq에서 제공하는 함수를 써보는 연습을 하도록 합시다.
import heapq
from typing import List
class Solution:
def maxProduct(self, nums: List[int]) -> int:
heapq.heapify(nums)
lst = heapq.nlargest(2,nums)
return (lst[0] -1) * (lst[1]-1)
행렬에서 제일 작은 k개 행 찾기
https://leetcode.com/problems/the-k-weakest-rows-in-a-matrix/
The K Weakest Rows in a Matrix - LeetCode
Can you solve this real interview question? The K Weakest Rows in a Matrix - You are given an m x n binary matrix mat of 1's (representing soldiers) and 0's (representing civilians). The soldiers are positioned in front of the civilians. That is, all the 1
leetcode.com
마찬가지로 리스트로도 풀 수 있는 문제지만, 힙 쓰는 연습을 해보는 문제.
from typing import List
import heapq
class Solution:
def kWeakestRows(self, mat: List[List[int]], k: int) -> List[int]:
heap = []
for i in range(len(mat)):
cnt = mat[i].count(1)
heapq.heappush(heap, (cnt, i))
return [heapq.heappop(heap)[1] for i in range(k)]
배열에서 K번째로 큰 원소
https://leetcode.com/problems/kth-largest-element-in-an-array/
Kth Largest Element in an Array - LeetCode
Can you solve this real interview question? Kth Largest Element in an Array - Given an integer array nums and an integer k, return the kth largest element in the array. Note that it is the kth largest element in the sorted order, not the kth distinct eleme
leetcode.com
sort를 하지않고 배열에서 k번째로 큰 원소를 구하는 문제.
힙은 처음부터 큰 순서대로 ( 또는 작은 순서대로 ) 정리되어서 들어가기 때문에, k번째로 큰 원소는 힙의 원소를 k번 뽑았을 때 리턴값이 될 것.
*참고로 힙을 구현해서 풀어보았습니다. 파이썬 heapq이용하면 간단하게 풀 수 있음! 후술하겠지만, 파이썬 힙은 minheap이라 거꾸로 구성해줘야 합니다.
from typing import List
class BinaryMaxHeap:
def __init__(self):
# 계산 편의를 위해 0이 아닌 1번째 인덱스부터 사용한다.
self.items = [None]
def __len__(self):
# len() 연산을 가능하게 하는 매직 메서드 덮어쓰기(Override).
return len(self.items) - 1
def _percolate_up(self):
# percolate: 스며들다.
cur = len(self)
# left 라면 2*cur, right 라면 2*cur + 1 이므로 parent 는 항상 cur // 2
parent = cur // 2
while parent > 0:
if self.items[cur] > self.items[parent]:
self.items[cur], self.items[parent] = self.items[parent], self.items[cur]
cur = parent
parent = cur // 2
def _percolate_down(self, cur):
biggest = cur
left = 2 * cur
right = 2 * cur + 1
if left <= len(self) and self.items[left] > self.items[biggest]:
biggest = left
if right <= len(self) and self.items[right] > self.items[biggest]:
biggest = right
if biggest != cur:
self.items[cur], self.items[biggest] = self.items[biggest], self.items[cur]
self._percolate_down(biggest)
def insert(self, k):
self.items.append(k)
self._percolate_up()
def extract(self):
if len(self) < 1:
return None
root = self.items[1]
self.items[1] = self.items[-1]
self.items.pop()
self._percolate_down(1)
return root
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
maxheap = BinaryMaxHeap()
for elem in nums:
maxheap.insert(elem)
return [maxheap.extract() for _ in range(k)][k-1]
최소힙
https://www.acmicpc.net/problem/1927
1927번: 최소 힙
첫째 줄에 연산의 개수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 N개의 줄에는 연산에 대한 정보를 나타내는 정수 x가 주어진다. 만약 x가 자연수라면 배열에 x라는 값을 넣는(추가하는) 연산이고, x가 0
www.acmicpc.net

2023.12.22 - [TIL/[순간순간 알게된 짧은 지식] TIL] - 파이썬 입출력 시간
파이썬 입출력 시간
https://www.acmicpc.net/problem/1927 1927번: 최소 힙 첫째 줄에 연산의 개수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 N개의 줄에는 연산에 대한 정보를 나타내는 정수 x가 주어진다. 만약 x가 자연수라면 배열에
mingtian-chan.tistory.com
완료 시간 관련 게시글은 이후에 따로 정리해서 올리도록 하겠습니다
파이썬 heapq를 그대로 이용해서 입출력만 빠르게 하면 되는 문제.
import heapq
import sys
heap = []
n = int(sys.stdin.readline().rstrip())
for _ in range(n):
i = int(sys.stdin.readline().rstrip())
if i == 0:
if heap:
print(heapq.heappop(heap))
else:
print(0)
else:
heapq.heappush(heap, i)
최대힙
https://www.acmicpc.net/problem/11279
11279번: 최대 힙
첫째 줄에 연산의 개수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 N개의 줄에는 연산에 대한 정보를 나타내는 정수 x가 주어진다. 만약 x가 자연수라면 배열에 x라는 값을 넣는(추가하는) 연산이고, x가 0
www.acmicpc.net
파이썬에서는 최소힙을 제공하므로, 넣는 데이터의 부호를 바꾸어주면 최대값이 최소값이 된다.
출력할 때는 다시 부호를 바꾸어서 출력.
'항해99 > [항해99] 알고리즘' 카테고리의 다른 글
[항해99] 정렬 ( quick, merge) (0) | 2023.12.25 |
---|---|
[항해99] 정렬 알고리즘 (0) | 2023.12.23 |
[항해99] 이진 탐색 트리 (BST) (0) | 2023.12.22 |
[항해99] 트리 (0) | 2023.12.22 |
[항해99] BFS 너비 우선 탐색 (0) | 2023.12.18 |