0Pricing
Coding Interview Prep · Ders

Açgözlü Yaklaşım mı DP mi: Hangisi Ne Zaman Kullanılır

Açgözlü seçim özelliğini ve değiş tokuş argümanını kullanarak açgözlü yaklaşımla çözülebilen problemleri, DP gerektirenlerden ayırt edin.

Açgözlü Yaklaşım mı DP mi: Hangisi Ne Zaman Kullanılır, CoddyKit'te ücretsiz bir Coding Interview Prep dersidir. Bu, 4 dersinin 1. 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.

Açgözlü ve DP'ye Genel Bakış

Hem Açgözlü hem de Dinamik Programlama, optimizasyon problemlerini, yani maksimumu, minimumu veya optimum düzenlemeyi bulma problemlerini çözer. Açgözlü yaklaşım, önceki kararları yeniden değerlendirmeden her adımda yerel olarak optimum seçimi yapar. DP tüm olasılıkları inceler, ancak yeniden hesaplamayı önlemek için önbelleğe alma kullanır. Hangisini uygulayacağınızı bilmek, yanlış bir açgözlü yaklaşımda hata ayıklamakla veya gereksiz yere karmaşık bir DP tablosu oluşturmakla harcayacağınız saatleri kurtarabilir.

# Greedy: always take the locally best option
# Example: coin change with coins [1, 5, 10, 25]
# Greedy: take as many 25s as possible, then 10s, etc.
# This works for standard denominations but NOT all coin sets!

# DP: explore all possibilities via memoisation
# Example: coin change with coins [1, 3, 4] and target 6
# Greedy would pick 4, then 1, 1 → 3 coins
# DP finds: 3 + 3 → 2 coins (optimal!)
print('Greedy can fail when local optimum != global optimum')

Açgözlü Seçim Özelliği

Bir problem, küresel olarak optimum bir çözümün her zaman yerel olarak optimum (açgözlü) seçimler yapılarak oluşturulabilmesi durumunda açgözlü seçim özelliğine sahiptir. Biçimsel olarak, açgözlü seçimle başlayan bir optimum çözüm vardır; bu nedenle hiçbir zaman geri izleme yapmamız gerekmez. Bunu kanıtlamak için genellikle bir değiş tokuş argümanı kullanılır: herhangi bir optimum çözümün açgözlü seçimi içermediğini varsayın, ardından işleri kötüleştirmeden bu seçimi çözümün içine alabileceğinizi gösterin.

# Exchange argument example: Activity Selection
# Greedy: always pick the activity that ends earliest
# Proof: suppose optimal solution starts with activity A (not earliest-ending)
# Let G be the earliest-ending activity.
# Replace A with G in the solution:
# - G ends no later than A, so G does not conflict with any activity A allowed
# - The solution remains valid with at least as many activities
# Therefore greedy choice (earliest end) is always safe.

activities = [(1,4), (3,5), (0,6), (5,7), (3,9), (5,9), (6,10), (8,11), (8,12), (2,14)]
activities.sort(key=lambda x: x[1])  # sort by end time
print('Sorted by end:', activities[:4], '...')

Optimum Alt Yapı

Hem açgözlü yaklaşım hem de DP, optimum alt yapı gerektirir: tüm problemin optimum çözümü, alt problemlerin optimum çözümlerini içerir. Aradaki fark, alt problemlerin optimum çözümlerinin tüm seçenekleri incelemeden açgözlü biçimde belirlenip belirlenememesi veya birden fazla seçeneğin karşılaştırılmasının gerekip gerekmediğidir. Bir seçim yaptığınızda kalan alt problem yapı bakımından aynıysa açgözlü yaklaşım işe yarar. Birkaç seçeneği karşılaştırmanız gerekiyorsa DP kullanın.

# Greedy works: activity selection
# Making the greedy choice (earliest-ending) leaves a sub-problem
# that is structurally identical (activity selection on remaining activities)
# and the greedy choice for the sub-problem is still valid.

# DP needed: 0/1 knapsack
# After choosing to include/exclude item i, the remaining sub-problem
# depends on WHICH item we chose — different choices yield different sub-problems.
# No single greedy rule works for all inputs.

print('Greedy: sub-problem is unique after each choice')
print('DP: sub-problem depends on which choice was made')

Örtüşen Alt Problemler: DP Sinyali

Özyinelemeli bir ayrıştırmada aynı alt problem birden çok kez çözülüyorsa, önbelleğe alma kullanan DP gerekir. Özyineleme ağacını çizin ve tekrarlanan düğümleri arayın. Fibonacci için fib(5) ağacında fib(3) iki kez hesaplanır. [1,3,4] madeni paraları ve 6 hedefiyle bozuk para değişimi probleminde, 3, 2 ve 1 hedeflerine ait alt problemler birden çok kez ortaya çıkar. Örtüşen alt problemler + optimum alt yapı = DP.

# Recursion tree for coin change [1,3,4], target=6
# bt(6) → bt(5) → bt(4) → bt(3) (repeated!)
#              → bt(2) → bt(1) (repeated!)
#         → bt(3) (repeated!)
#       → bt(2) (repeated!)

# Without memoisation: exponential time
# With DP table: O(target * len(coins)) time

def coin_change_dp(coins, amount):
    dp = [float('inf')] * (amount + 1)
    dp[0] = 0
    for a in range(1, amount + 1):
        for c in coins:
            if c <= a:
                dp[a] = min(dp[a], dp[a - c] + 1)
    return dp[amount] if dp[amount] != float('inf') else -1

print(coin_change_dp([1, 3, 4], 6))  # 2 (3+3)
print(coin_change_dp([2], 3))        # -1 (impossible)

Klasik Açgözlü Problemler

Açgözlü yaklaşımın doğruluğunun kanıtlandığı problemler: (1) Etkinlik/Aralık Çizelgeleme — en erken bitiş zamanına göre açgözlü yaklaşım. (2) Minimum Örten Ağaç — Prim ve Kruskal algoritmaları. (3) Huffman Kodlaması — her zaman frekansı en düşük iki düğümü birleştirme. (4) Kesirli Sırt Çantası — öğeleri en yüksek değer/ağırlık oranına göre alma. (5) Zıplama Oyunu — erişilebilen en büyük dizin değerini izleme. Tüm bunlar, değiş tokuş argümanıyla kanıtlanabilir.

# Fractional Knapsack: greedy works
def fractional_knapsack(items, capacity):
    # Sort by value/weight ratio descending
    items.sort(key=lambda x: x[1]/x[0], reverse=True)
    total = 0
    for weight, value in items:
        if capacity <= 0: break
        take = min(weight, capacity)
        total += take * (value / weight)
        capacity -= take
    return total

items = [(10, 60), (20, 100), (30, 120)]  # (weight, value)
print(fractional_knapsack(items, 50))  # 240.0

# 0/1 Knapsack: greedy FAILS
# Must use DP (can't take fractions)

Açgözlü Yöntem Başarısız Olduğunda: Karşı Örnekler

Bir karşı örnek bulmak, açgözlü bir varsayımı çürütmenin en hızlı yoludur. [1, 3, 4] madeni paraları ve 6 hedefiyle bozuk para değişimi probleminde açgözlü yaklaşım (en büyükten başlayarak) 4'ü, ardından 1+1'i alır ve 3 madeni para kullanır. DP ise 3+3'ü bulur ve 2 madeni para kullanır. 0/1 sırt çantası probleminde orana göre açgözlü seçim, oranı en iyi olan öğeyi alır; ancak kapasiteyi daha iyi dolduran kombinasyonları gözden kaçırabilir. Bir dakikadan kısa sürede karşı örnek oluşturabiliyorsanız DP'ye geçin.

# Counterexample: coin change with non-standard coins
def greedy_coins(coins, amount):
    coins.sort(reverse=True)
    count = 0
    for c in coins:
        while amount >= c:
            amount -= c
            count += 1
    return count if amount == 0 else -1

def dp_coins(coins, amount):
    dp = [float('inf')] * (amount + 1)
    dp[0] = 0
    for a in range(1, amount + 1):
        for c in coins:
            if c <= a: dp[a] = min(dp[a], dp[a-c] + 1)
    return dp[amount] if dp[amount] < float('inf') else -1

coins, target = [1, 3, 4], 6
print('Greedy:', greedy_coins(coins[:], target))  # 3 (4+1+1)
print('DP:    ', dp_coins(coins, target))          # 2 (3+3)

Karşılaştırma Tablosu: Açgözlü ve DP

Temel farklar yan yana: Zaman karmaşıklığı — açgözlü yaklaşımda genellikle O(n log n) (sıralama baskındır); DP'de O(n × durum sayısı). Alan karmaşıklığı — açgözlü yaklaşımda O(1) ek alan; DP'de O(durum sayısı). Doğruluk — açgözlü yaklaşım için kanıt gerekir; durumlar ve yineleme bağıntısı doğruysa DP her zaman doğrudur. Uygulanabilirlik — çizelgeleme, örten ağaçlar ve Huffman için açgözlü yaklaşım; sırt çantası, dizi hizalama ve negatif ağırlıklı en kısa yol için DP.

# Performance comparison
import time

def time_it(func, *args):
    start = time.time()
    result = func(*args)
    return result, time.time() - start

# Large coin change test
coins = [1, 5, 10, 25, 100]
amount = 10000

def dp_coins(coins, amount):
    dp = [float('inf')] * (amount + 1)
    dp[0] = 0
    for a in range(1, amount + 1):
        for c in coins:
            if c <= a: dp[a] = min(dp[a], dp[a-c]+1)
    return dp[amount]

result, elapsed = time_it(dp_coins, coins, amount)
print(f'DP coin change(amount={amount}): {result} coins in {elapsed:.4f}s')

Karar Çerçevesi

Mülakat karar akış şeması: (1) Açgözlü seçim özelliğini bir değiş tokuş argümanıyla kanıtlayabilir misiniz? Evetse → açgözlü yaklaşım. (2) Alt problemler örtüşüyor mu (aynı duruma birden çok yoldan ulaşılıyor mu)? Evetse → DP. (3) Problem tüm çözümleri saymanızı veya listelemenizi mi istiyor? → DP veya geri izleme. (4) Problem doğal bir sıralamaya sahip tek bir optimum değer mi istiyor? Açgözlü yaklaşımdan şüphelenin. (5) Emin değilseniz DP'yi kodlayın; yineleme bağıntısı doğruysa daha yavaş olsa bile her zaman doğrudur.

# Decision questions to ask:
questions = [
    '1. Is there a natural ordering (by time, ratio, size)?',
    '2. Does making the greedy choice leave a smaller same-type problem?',
    '3. Can I construct a counterexample quickly?',
    '4. Are sub-problems reused across different choice sequences?',
    '5. Does the problem involve counting or listing (not just optimising)?',
]
for q in questions:
    print(q)

print()
print('Greedy signals: scheduling, spanning tree, Huffman, jump game')
print('DP signals: knapsack, edit distance, LCS, coin change (general)')

Aralık Problemleri: Açgözlü ve DP

Aralık problemleri açgözlü yaklaşım ile DP arasında ayrılır. Çakışmayan aralıklar (en az sayıda remove işlemi): bitiş zamanına göre sort yapın ve aralıkları açgözlü biçimde seçin; açgözlü yaklaşımın optimum olduğu kanıtlanmıştır. Ağırlıklı aralık çizelgeleme (toplam ağırlığı en yüksek duruma getirme): ağır aralıklar birçok hafif aralıkla çakışabileceğinden ve tüm geçerli alt kümelerin karşılaştırılması gerektiğinden DP gerekir. Ayırt edici faktör, tüm aralıkların eşit ağırlıkta mı (açgözlü yaklaşım) yoksa değişken ağırlıkta mı (DP) olduğudur.

# Non-overlapping intervals: greedy works
def erase_overlap_intervals(intervals):
    if not intervals: return 0
    intervals.sort(key=lambda x: x[1])
    count = 0
    last_end = float('-inf')
    for start, end in intervals:
        if start >= last_end:
            last_end = end  # keep this interval
        else:
            count += 1  # remove this interval
    return count

print(erase_overlap_intervals([[1,2],[2,3],[3,4],[1,3]]))  # 1
print(erase_overlap_intervals([[1,2],[1,2],[1,2]]))        # 2

Problem Sinyallerini Tanıma

Problem ifadelerinde sık görülen sinyaller: 'minimum işlem sayısı', 'maksimum kâr', 'optimum seçim' → açgözlü yaklaşım veya DP olabilir; örtüşme durumunu denetleyin. 'yöntemlerin sayısını hesapla' → her zaman DP. 'geçerli herhangi bir çizelge bul' → açgözlü yaklaşım olabilir. 'tüm olasılıklar' → geri izleme. 'bitişik olanları alamaz' → DP (ev soyguncusu). 'toplantılar, aralıklar, görevler' → büyük olasılıkla açgözlü yaklaşım. Sinyalleri algoritma aileleriyle eşleştirmek, mülakat problemlerini daha hızlı teşhis etmenizi sağlar.

# Signal-to-algorithm mapping
signals = {
    'minimum steps/coins/operations': 'DP (unless trivially greedy)',
    'maximum profit/value with constraint': 'DP (knapsack family)',
    'count ways to reach/achieve': 'DP (always)',
    'all combinations/permutations': 'Backtracking',
    'schedule tasks within time': 'Greedy (sort by deadline/end)',
    'cannot pick adjacent': 'DP (house robber pattern)',
    'free to pick any subset': 'DP or Greedy (check overlap)',
    'interval merging/selecting': 'Greedy (sort by end time)',
}
for signal, algo in signals.items():
    print(f'{signal!r}: → {algo}')

Açgözlü Yöntemin Doğruluğunu Kanıtlama

Bir açgözlü algoritmanın doğruluğunu kanıtlamak için değiş tokuş argümanını kullanın: (1) İlk seçimde açgözlü çözüm G'den farklı olan bir optimum çözüm OPT bulunduğunu varsayın. (2) Amaç değerini artırmadan açgözlü seçimi OPT'nin içine alabileceğinizi gösterin. (3) Tümevarım yoluyla açgözlü çözümün herhangi bir optimum çözüm kadar iyi olduğu sonucuna varın. Mülakatlarda tam bir kanıta ihtiyacınız yoktur; ancak değiş tokuş argümanının ardındaki sezgiyi açıklamak, konuyu derinlemesine anladığınızı gösterir.

# Exchange argument demo: earliest-finish-time activity selection
# Suppose OPT starts with activity A (not earliest-ending)
# Let G = earliest-ending activity available
# A.end >= G.end (G ends earlier or same time)

# Swap A for G in OPT:
# - G.end <= A.end, so G does not conflict with anything A allowed after it
# - OPT remains valid with the same number of activities
# - Repeat: after swap, OPT begins with G, matching greedy first choice
# By induction, OPT can be transformed to match G activity by activity
# without losing activities → greedy is optimal

print('Exchange argument: any OPT can be modified to match Greedy without loss')
print('This proves Greedy >= OPT in objective value')

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: açgözlü yaklaşım, açgözlü seçim özelliği geçerli olduğunda doğrudur ve bu durum değiş tokuş argümanıyla kanıtlanabilir; alt problemler örtüştüğünde (aynı alt probleme birden çok yoldan ulaşıldığında) ve tek bir açgözlü kuralla çözülemediğinde DP gerekir; ayrıca açgözlü bir varsayımı çürütmenin en hızlı yolu, standart dışı girdilerle bir karşı örnek oluşturmaktır. Sırada, Aralık Çizelgeleme ve Birleştirme problemlerini bitiş zamanına göre sort yaklaşımıyla çözeceğiz.

Sıkça Sorulan Sorular

“Açgözlü Yaklaşım mı DP mi: Hangisi Ne Zaman Kullanılır” dersi ücretsiz mi?

Evet — “Açgözlü Yaklaşım mı DP mi: Hangisi Ne Zaman Kullanılır” 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.

“Açgözlü Yaklaşım mı DP mi: Hangisi Ne Zaman Kullanılır” dersinde ne öğreneceğim?

Açgözlü seçim özelliğini ve değiş tokuş argümanını kullanarak açgözlü yaklaşımla çözülebilen problemleri, DP gerektirenlerden ayırt edin. 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 1. dersidir.

“Açgözlü Yaklaşım mı DP mi: Hangisi Ne Zaman Kullanılır” 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

  1. Açgözlü Yaklaşım mı DP mi: Hangisi Ne Zaman Kullanılır
  2. Aralık Çizelgeleme ve Birleştirme
  3. Sıçrama Oyunu I ve II
  4. Görev Çizelgeleyici ve Benzin İstasyonu
← Coding Interview Prep Sayfasına Dön