heapq Python dan Trik Max-Heap
Gunakan heapq.heappush/heappop, negasikan nilai untuk mensimulasikan max-heap, dan terapkan heapq.nlargest/nsmallest untuk kueri top-k dengan cepat.
heapq Python dan Trik Max-Heap adalah pelajaran DSA Interview Prep gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar DSA Interview Prep, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus DSA Interview Prep mencakup 4 pelajaran total.
Gambaran Umum Modul heapq Python
Modul heapq Python menyediakan tumpukan minimum yang dibangun di atas list Python biasa. Berbeda dari kelas tumpukan khusus, heapq beroperasi langsung pada list yang sudah ada. Fungsi-fungsi modul ini adalah: heapify untuk membangun tumpukan dalam O(n), heappush untuk menambahkan elemen dalam O(log n), heappop untuk menghapus elemen minimum dalam O(log n), serta heappushpop / heapreplace untuk efisiensi gabungan.
import heapq
# heapq operates on plain Python lists
heap = []
heapq.heappush(heap, 5)
heapq.heappush(heap, 2)
heapq.heappush(heap, 8)
heapq.heappush(heap, 1)
print('Heap array:', heap) # internal array (not sorted!)
print('Peek min:', heap[0]) # O(1) min access
print('Pop min:', heapq.heappop(heap)) # 1
print('Next min:', heap[0]) # 2
# heapify: turn any list into a heap in O(n)
data = [9, 4, 7, 1, 3, 6, 2]
heapq.heapify(data)
print('Heapified:', data, '| min:', data[0])Tumpukan Maksimum dengan Menegasikan Nilai
heapq Python hanya menyediakan tumpukan minimum. Untuk menyimulasikan tumpukan maksimum, negasikan semua nilai sebelum melakukan push dan negasikan lagi saat melakukan pop. Hal ini berhasil karena tumpukan mengurutkan berdasarkan nilai yang disimpan, sedangkan negasi membalik urutannya. Selalu ingat untuk melakukan negasi di kedua sisi: negasikan sebelum push dan setelah pop. Lupa melakukan salah satunya merupakan kesalahan umum dalam wawancara.
import heapq
max_heap = []
for val in [5, 1, 8, 3, 9, 2]:
heapq.heappush(max_heap, -val) # negate on push
print('Max-heap internal:', max_heap) # all negated
# Pop in descending order:
results = []
while max_heap:
results.append(-heapq.heappop(max_heap)) # negate on pop
print('Sorted descending:', results) # [9, 8, 5, 3, 2, 1]
# Common pattern: top-k largest
data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
k = 3
heap = []
for x in data:
heapq.heappush(heap, -x)
print('Top', k, ':', [-heapq.heappop(heap) for _ in range(k)])heapq.nlargest dan nsmallest
heapq.nlargest(k, iterable) dan heapq.nsmallest(k, iterable) mengembalikan k item terbesar atau terkecil. Keduanya memiliki kompleksitas O(n log k), lebih efisien daripada pengurutan penuh (O(n log n)) ketika k jauh lebih kecil daripada n. Secara internal, keduanya menggunakan tumpukan berukuran k. Ketika k mendekati n, Python beralih ke pengurutan penuh. Gunakan fungsi-fungsi ini untuk kueri k teratas sekali jalan tanpa harus mempertahankan tumpukan secara terus-menerus.
import heapq
data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 7]
# Top 3 largest:
print(heapq.nlargest(3, data)) # [9, 8, 7]
# Top 3 smallest:
print(heapq.nsmallest(3, data)) # [1, 1, 2]
# With a key function:
words = ['banana', 'apple', 'cherry', 'date', 'elderberry']
print(heapq.nlargest(2, words, key=len)) # ['elderberry', 'banana']
print(heapq.nsmallest(2, words, key=len)) # ['date', 'apple']
# Note: when k ~ n, use sorted() instead:
# sorted(data)[-k:] or sorted(data, reverse=True)[:k]Tumpukan dengan Tuple untuk Kunci Kompleks
Ketika elemen tumpukan memerlukan kunci perbandingan khusus, simpan elemen tersebut sebagai tuple (priority, data). heapq Python membandingkan tuple elemen demi elemen, sehingga prioritas dibandingkan terlebih dahulu. Jika prioritasnya sama, elemen kedua akan dibandingkan—hal ini dapat menyebabkan error jika datanya tidak dapat dibandingkan. Pola yang paling aman adalah menyertakan penghitung unik sebagai pemecah seri agar elemen data tidak pernah dibandingkan secara langsung.
import heapq
import itertools
# Pattern: (priority, counter, item)
# Counter ensures unique tiebreaker, avoids comparing items
counter = itertools.count()
heap = []
def push_task(priority, task):
heapq.heappush(heap, (priority, next(counter), task))
push_task(3, 'low priority task')
push_task(1, 'high priority task')
push_task(2, 'medium priority task')
push_task(1, 'another high priority')
while heap:
pri, cnt, task = heapq.heappop(heap)
print(f'P{pri}: {task}')
# Output in priority order: P1, P1, P2, P3heapq.merge: Menggabungkan Iterable Terurut
heapq.merge(*iterables) menggabungkan beberapa iterable terurut secara bertahap menjadi satu keluaran terurut tanpa memuat seluruh data ke memori. Proses ini setara dengan penggabungan k-arah menggunakan tumpukan minimum berukuran k dan digunakan dalam algoritma pengurutan eksternal. Fungsi ini mengembalikan iterator, sehingga elemen dihasilkan satu per satu—ideal untuk kumpulan data besar atau skenario aliran data.
import heapq
# Merge multiple sorted lists efficiently
sorted_lists = [
[1, 5, 9],
[2, 6, 8],
[3, 4, 7]
]
# heapq.merge takes sorted iterables and returns a merged sorted iterator
merged = list(heapq.merge(*sorted_lists))
print('Merged:', merged) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# The k-way merge manually (educational version):
def merge_k_sorted(lists):
heap = []
for i, lst in enumerate(lists):
if lst:
heapq.heappush(heap, (lst[0], i, 0))
result = []
while heap:
val, list_idx, elem_idx = heapq.heappop(heap)
result.append(val)
if elem_idx + 1 < len(lists[list_idx]):
heapq.heappush(heap, (lists[list_idx][elem_idx+1], list_idx, elem_idx+1))
return result
print('Manual k-way:', merge_k_sorted(sorted_lists))Pola Penghapusan Tertunda untuk Tumpukan
Ketika Anda perlu menghapus elemen sembarang dari tumpukan tetapi tidak mengetahui indeksnya, gunakan penghapusan tertunda: tandai elemen sebagai terhapus dalam himpunan terpisah, lalu lewati elemen tersebut saat melakukan pop. Kompleksitasnya O(log n) secara diamortisasi dan pola ini menghindari kerumitan pelacakan indeks. Ini merupakan pendekatan standar dalam algoritma Dijkstra dengan entri duplikat dan simulasi penjadwal tugas.
import heapq
class LazyHeap:
def __init__(self):
self._heap = []
self._removed = set()
def push(self, task):
heapq.heappush(self._heap, task)
def remove(self, task):
self._removed.add(task) # mark as removed
def pop(self):
while self._heap:
task = heapq.heappop(self._heap)
if task not in self._removed:
return task
return None
lh = LazyHeap()
for t in [5, 1, 8, 3, 2]:
lh.push(t)
lh.remove(1) # 'delete' 1 lazily
lh.remove(8) # 'delete' 8 lazily
results = [lh.pop() for _ in range(3)]
print(results) # [2, 3, 5] -- 1 and 8 skippedElemen Terbesar ke-K dalam Aliran Data
Elemen Terbesar ke-K dalam Aliran Data (LeetCode #703) mempertahankan tumpukan minimum berukuran k. Akar tumpukan selalu merupakan elemen terbesar ke-k yang ditemukan sejauh ini. Saat angka baru tiba, lakukan push terhadapnya, lalu jika ukuran tumpukan melebihi k, lakukan pop terhadap elemen minimum. Akar selalu merupakan elemen terbesar ke-k karena tepat ada k-1 elemen yang lebih besar darinya di dalam tumpukan.
import heapq
class KthLargest:
def __init__(self, k, nums):
self.k = k
self.heap = []
for num in nums:
self.add(num)
def add(self, val):
heapq.heappush(self.heap, val)
if len(self.heap) > self.k:
heapq.heappop(self.heap) # remove smallest
return self.heap[0] # kth largest = root of min-heap
# k=3, initial=[4,5,8,2]
kl = KthLargest(3, [4, 5, 8, 2])
print(kl.add(3)) # 4 (top 3: 8,5,4 -- kth=4)
print(kl.add(5)) # 5 (top 3: 8,5,5 -- kth=5)
print(kl.add(10)) # 5 (top 3: 10,8,5 -- kth=5)
print(kl.add(9)) # 8 (top 3: 10,9,8 -- kth=8)Menemukan K Pasangan dengan Jumlah Terkecil
Menemukan K pasangan dengan jumlah terkecil (LeetCode #373) menggunakan tumpukan minimum untuk menghasilkan pasangan secara berurutan. Mulailah dengan semua pasangan (nums1[0], nums2[j]) untuk setiap j. Lakukan pop terhadap elemen minimum, lalu untuk pasangan yang diambil (nums1[i], nums2[j]), lakukan push terhadap (nums1[i+1], nums2[j])—kandidat berikutnya dari kolom nums2 yang sama. Ini merupakan pola umum untuk menghasilkan pasangan atau produk terurut dengan tumpukan.
import heapq
def k_smallest_pairs(nums1, nums2, k):
if not nums1 or not nums2:
return []
heap = []
# Initialize with pairs (nums1[0], nums2[j])
for j in range(min(k, len(nums2))):
heapq.heappush(heap, (nums1[0] + nums2[j], 0, j))
result = []
while heap and len(result) < k:
total, i, j = heapq.heappop(heap)
result.append([nums1[i], nums2[j]])
if i + 1 < len(nums1):
heapq.heappush(heap, (nums1[i+1] + nums2[j], i+1, j))
return result
print(k_smallest_pairs([1,7,11], [2,4,6], 3))
# [[1,2], [1,4], [1,6]]Penjadwal Tugas dengan Tumpukan Maksimum
Penjadwal Tugas (LeetCode #621) meminta Anda mencari waktu minimum untuk menjadwalkan n tugas dengan periode jeda n interval di antara tugas yang sama. Gunakan tumpukan maksimum berisi frekuensi tugas: pada setiap langkah waktu, pilih tugas tersedia dengan frekuensi tertinggi, kurangi jumlahnya, lalu masukkan tugas tersebut ke dalam masa jeda. Proses k=n+1 tugas per siklus (atau penuhi sisanya dengan waktu menganggur). Pendekatan serakah dengan tumpukan maksimum ini menghasilkan jawaban optimal.
import heapq
from collections import Counter
def least_interval(tasks, n):
freq = Counter(tasks)
heap = [-f for f in freq.values()] # max-heap (negated)
heapq.heapify(heap)
time = 0
while heap:
cycle = n + 1
temp = []
for _ in range(cycle):
if heap:
temp.append(heapq.heappop(heap))
for f in temp:
if f + 1 < 0: # still tasks remaining
heapq.heappush(heap, f + 1)
# Add full cycle or remaining tasks if queue empty
time += cycle if heap else len(temp)
return time
print(least_interval(['A','A','A','B','B','B'], 2)) # 8
print(least_interval(['A','A','A','B','B','B'], 0)) # 6Tumpukan dalam Algoritma Dijkstra
Antrean prioritas dalam algoritma Dijkstra diimplementasikan menggunakan tumpukan minimum. Simpan tuple (distance, node) dan selalu proses simpul belum dikunjungi yang paling dekat terlebih dahulu. Saat Anda mengambil simpul dengan jarak yang lebih besar daripada jalur terpendek yang saat ini diketahui—entri usang akibat penghapusan tertunda—lewati simpul tersebut. Cara ini menghilangkan kebutuhan akan operasi pengurangan kunci dan menjaga implementasi tetap sederhana dengan kompleksitas O((V + E) log V).
import heapq
def dijkstra(graph, start):
dist = {node: float('inf') for node in graph}
dist[start] = 0
heap = [(0, start)] # (distance, node)
while heap:
d, u = heapq.heappop(heap)
if d > dist[u]: # stale entry, skip
continue
for v, w in graph[u]:
if dist[u] + w < dist[v]:
dist[v] = dist[u] + w
heapq.heappush(heap, (dist[v], v))
return dist
graph = {
'A': [('B', 4), ('C', 1)],
'B': [('D', 1)],
'C': [('B', 2), ('D', 5)],
'D': []
}
print(dijkstra(graph, 'A')) # {'A':0,'B':3,'C':1,'D':4}Menyusun Ulang String dengan Tumpukan Maksimum
Menyusun Ulang String (LeetCode #767) meminta Anda menyusun ulang string agar tidak ada dua karakter yang bersebelahan dan sama. Gunakan tumpukan maksimum berisi (-frequency, char). Pada setiap langkah, lakukan pop terhadap karakter dengan frekuensi tertinggi. Jika karakter sebelumnya sama dengan karakter yang paling sering muncul, lakukan pop terhadap karakter dengan frekuensi tertinggi kedua. Pendekatan serakah ini memastikan karakter yang paling sulit ditempatkan diletakkan sedini mungkin.
import heapq
from collections import Counter
def reorganize_string(s):
freq = Counter(s)
heap = [(-f, c) for c, f in freq.items()]
heapq.heapify(heap)
result = []
prev_freq, prev_char = 0, ''
while heap:
freq, char = heapq.heappop(heap)
result.append(char)
# Push back the previous character if still remaining
if prev_freq < 0:
heapq.heappush(heap, (prev_freq, prev_char))
prev_freq, prev_char = freq + 1, char # decrement freq (less negative)
result_str = ''.join(result)
# Verify no adjacent duplicates
return result_str if len(result_str) == len(s) else ''
print(reorganize_string('aab')) # 'aba'
print(reorganize_string('aaab')) # '' (impossible)Pemeriksaan Singkat
Uji pemahaman Anda tentang konsep Struktur Data & Algoritma — Persiapan Wawancara Pemrograman dari pelajaran ini.
Rangkuman Pelajaran
Dalam pelajaran ini Anda mempelajari: API modul heapq Python, termasuk heapify, heappush, heappop, nlargest, nsmallest, dan merge, simulasi tumpukan maksimum dengan menegasikan nilai, serta pola umum tumpukan dalam wawancara, termasuk aliran data k teratas, elemen terbesar ke-k dalam aliran data, penjadwal tugas, dan Dijkstra. Selanjutnya, kita akan membahas median dari aliran data dan penggabungan k-arah.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “heapq Python dan Trik Max-Heap” gratis?
Ya — teks lengkap “heapq Python dan Trik Max-Heap” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus DSA Interview Prep, upgrade ke CoddyKit PRO. Kursus DSA Interview Prep mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “heapq Python dan Trik Max-Heap”?
Gunakan heapq.heappush/heappop, negasikan nilai untuk mensimulasikan max-heap, dan terapkan heapq.nlargest/nsmallest untuk kueri top-k dengan cepat. Kamu berlatih DSA Interview Prep dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai DSA Interview Prep?
Tidak diperlukan pengalaman sebelumnya. DSA Interview Prep di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “heapq Python dan Trik Max-Heap” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran DSA Interview Prep ini?
Ya. Setiap pelajaran DSA Interview Prep menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Sifat Heap dan Representasi Array
- Heapify, Push, dan Pop dari Awal
- heapq Python dan Trik Max-Heap
- Median dari Aliran Data dan Penggabungan K Arah