Python heapq ve Maksimum Yığın Taktikleri
heapq.heappush/heapq.heappop kullanın, maksimum yığını benzetmek için değerleri negatif yapın ve hızlı ilk-k sorguları için heapq.nlargest/heapq.nsmallest uygulayın.
Python heapq ve Maksimum Yığın Taktikleri, CoddyKit'te ücretsiz bir Coding Interview Prep dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Coding Interview Prep öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Coding Interview Prep kursu toplamda 4 dersten oluşur.
Python heapq Modülüne Genel Bakış
Python'un heapq modülü, normal bir Python listesi üzerinde uygulanan bir min-yığın sağlar. Özel bir yığın sınıfının aksine, heapq mevcut listeler üzerinde yerinde çalışır. Modülün işlevleri şunlardır: O(n) sürede yığın oluşturmak için heapify, O(log n) sürede bir öğe eklemek için heappush, O(log n) sürede minimum öğeyi kaldırmak için heappop ve birlikte kullanıldığında verimlilik sağlayan heappushpop / heapreplace.
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])Değerlerin İşaretini Değiştirerek Maks-Yığın
Python'un heapq modülü yalnızca bir min-yığın sağlar. Bir maks-yığını benzetmek için, tüm değerleri push işleminden önce negatife çevirin ve pop işleminden sonra tekrar negatifini alın. Bu yöntem çalışır; çünkü yığın saklanan değerlere göre sıralama yapar ve işareti değiştirmek sıralamayı tersine çevirir. Her iki tarafta da işareti değiştirmeyi unutmayın: push işleminden önce negatife çevirin, pop işleminden sonra tekrar negatife çevirin. Adımlardan birini unutmak, mülakatlarda sık yapılan bir hatadır.
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 ve nsmallest
heapq.nlargest(k, iterable) ve heapq.nsmallest(k, iterable), en büyük veya en küçük k öğeyi döndürür. Bunların karmaşıklığı O(n log k)'dir; k, n'den çok daha küçük olduğunda tam sıralamaya (O(n log n)) göre daha verimlidirler. İçeride k boyutunda bir yığın kullanırlar. k, n'e yaklaştığında Python tam sıralamaya geri döner. Kalıcı bir yığın tutmadan tek seferlik en büyük veya en küçük k sorguları için bunları kullanın.
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]Karmaşık Anahtarlar için Demetlerle Yığın
Yığın öğeleri için özel bir karşılaştırma anahtarı gerektiğinde, öğeleri (priority, data) demetleri olarak saklayın. Python'un heapq'si demetleri öğe öğe karşılaştırır; bu nedenle önce öncelikleri karşılaştırır. Öncelikler eşitse ikinci öğeyi karşılaştırır. Veriler karşılaştırılabilir değilse bu durum hatalara yol açabilir. En güvenli yaklaşım, veri öğelerinin doğrudan karşılaştırılmasını önlemek için eşitlik bozucu olarak benzersiz bir sayaç eklemektir.
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: Sıralı Yinelenebilirleri Birleştirme
heapq.merge(*iterables), birden çok sıralı yinelenebileni tüm verileri belleğe yüklemeden tembel biçimde tek bir sıralı çıktıda birleştirir. Bu işlem, k boyutunda bir min-yığın kullanan k-yollu birleştirmeye eşdeğerdir ve harici sıralama algoritmalarında kullanılır. Bir yineleyici döndürür; bu nedenle öğeler birer birer üretilir. Bu özellik, büyük veri kümeleri veya akış senaryoları için idealdir.
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))Yığınlar için Tembel Silme Deseni
Bir yığından dizinini bilmediğiniz keyfi öğeleri kaldırmanız gerektiğinde tembel silme yöntemini kullanın: öğeleri ayrı bir kümede silinmiş olarak işaretleyin, ardından pop sırasında bunları atlayın. Bu yöntem amorti edilmiş O(log n) karmaşıklığa sahiptir ve dizinleri takip etmenin karmaşıklığını ortadan kaldırır. Yinelenen kayıtlar içeren Dijkstra algoritmasında ve görev zamanlayıcı benzetimlerinde kullanılan standart yaklaşım budur.
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 skippedAkıştaki K'inci En Büyük Öğe
Akıştaki K'inci En Büyük Öğe (LeetCode #703), k boyutunda bir min-yığın tutar. Yığının kökü, o ana kadar görülen k'inci en büyük öğedir. Yeni bir sayı geldiğinde onu push edin; yığın k boyutunu aşarsa minimumu pop edin. Kök her zaman k'inci en büyük öğedir, çünkü yığında ondan büyük tam olarak k-1 öğe bulunur.
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)Toplamı En Küçük K Çifti Bulma
Toplamları en küçük K çifti bulma (LeetCode #373), çiftleri sırayla üretmek için bir min-yığın kullanır. Her j için tüm (nums1[0], nums2[j]) çiftleriyle başlayın. Minimumu pop edin ve pop edilen (nums1[i], nums2[j]) çifti için aynı nums2 sütunundaki bir sonraki aday olan (nums1[i+1], nums2[j]) çiftini push edin. Bu, yığın kullanarak sıralı çift veya çarpım üretiminde yaygın bir örüntüdür.
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]]Maks-Yığın ile Görev Zamanlayıcı
Görev Zamanlayıcı (LeetCode #621), aynı görevler arasında n aralık soğuma süresi olacak şekilde n görevi zamanlamak için gereken minimum süreyi bulmanızı ister. Görev sıklıklarından oluşan bir maks-yığın kullanın: her zaman adımında kullanılabilir görevler arasından en sık görüleni seçin, sayısını azaltın ve soğuma süresine alın. Her döngüde k=n+1 görev işleyin veya kalan süreyi boşta kalma süresiyle doldurun. Maks-yığın kullanan bu açgözlü yaklaşım en iyi sonucu verir.
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)) # 6Dijkstra Algoritmasında Yığın
Dijkstra algoritmasındaki öncelik kuyruğu bir min-yığınla uygulanır. (distance, node) demetlerini saklayın ve her zaman ziyaret edilmemiş en yakın düğümü önce işleyin. Bir düğümü, o düğüm için o anda bilinen en kısa yoldan daha büyük bir uzaklıkla pop ederseniz, bu kaydı atlayın; bu, tembel silmeden kalan eski bir kayıttır. Böylece anahtar azaltma işlemine gerek kalmaz, uygulama basit kalır ve O((V + E) log V) karmaşıklığı korunur.
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}Dizeyi Maks-Yığın ile Yeniden Düzenleme
Dizeyi Yeniden Düzenleme (LeetCode #767), bitişik iki karakterin aynı olmayacağı şekilde bir dizeyi yeniden düzenlemenizi ister. (-frequency, char) biçiminde bir maks-yığın kullanın. Her adımda sıklığı en yüksek karakteri pop edin. Önceki karakter en sık görülen karakterle aynıysa, sıklığı en yüksek ikinci karakteri pop edin. Bu açgözlü yaklaşım, en fazla kısıtlanan karakterin mümkün olduğunca erken yerleştirilmesini sağlar.
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)Hızlı Kontrol
Bu dersteki Veri Yapıları & Algoritmalar — Kodlama Mülakatı Hazırlığı kavramlarını ne kadar anladığınızı sınayın.
Ders Özeti
Bu derste şunları öğrendiniz: heapify, heappush, heappop, nlargest, nsmallest ve merge işlevlerini içeren Python'un heapq modülü API'sini, değerlerin işaretini değiştirerek maks-yığın benzetimini ve akışta en büyük k öğe, akıştaki k'inci en büyük öğe, görev zamanlayıcı ve Dijkstra gibi yaygın yığın mülakat örüntülerini. Sırada veri akışından medyanı ve k-yollu birleştirmeyi ele alacağız.
Sıkça Sorulan Sorular
“Python heapq ve Maksimum Yığın Taktikleri” dersi ücretsiz mi?
Evet — “Python heapq ve Maksimum Yığın Taktikleri” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Coding Interview Prep kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Coding Interview Prep kursu toplamda 4 dersten oluşur.
“Python heapq ve Maksimum Yığın Taktikleri” dersinde ne öğreneceğim?
heapq.heappush/heapq.heappop kullanın, maksimum yığını benzetmek için değerleri negatif yapın ve hızlı ilk-k sorguları için heapq.nlargest/heapq.nsmallest uygulayın. Coding Interview Prep ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Coding Interview Prep öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Coding Interview Prep, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“Python heapq ve Maksimum Yığın Taktikleri” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Coding Interview Prep dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Coding Interview Prep dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Yığın Özelliği ve Dizi Gösterimi
- Yığın Oluşturma, Ekleme ve Çıkarma İşlemlerini Sıfırdan Uygulama
- Python heapq ve Maksimum Yığın Taktikleri
- Veri Akışından Medyan ve K-Yollu Birleştirme