Een greedy algoritme bouwt stap voor stap een oplossing op, waarbij het altijd de optie kiest die er op dit moment het beste uitziet - zonder eerdere keuzes te heroverwegen. Geen backtracking, geen vooruitkijken.
Het werkt als twee eigenschappen gelden:
Gegeven een verzameling activiteiten met begin- en eindtijden: selecteer het maximale aantal niet-overlappende activiteiten.
Greedy strategie: sorteer op eindtijd, kies altijd de activiteit die het eerst eindigt.
def max_activities(intervals):
intervals.sort(key=lambda x: x[1])
count, end = 0, 0
for s, e in intervals:
if s >= end:
count += 1
end = e
return count
Waarom werkt dit? De activiteit kiezen die het eerst eindigt, laat de meeste ruimte voor toekomstige activiteiten. Geen andere keuze kan beter zijn.
Bouw een optimale prefixvrije binaire code door herhaaldelijk de twee laagste-frequentie symbolen samen te voegen. Dit is greedy: bij elke stap voeg je het goedkoopste paar samen. Het resultaat is een boom waarin frequente symbolen korte codes krijgen.
Gegeven een array waarbij nums[i] de maximale spronglengte is vanaf index i: bepaal of je de laatste index kunt bereiken.
Greedy aanpak: houd de verst bereikbare index bij. Scan van links naar rechts - als je ooit achterraakt, return false.
def can_jump(nums):
farthest = 0
for i, jump in enumerate(nums):
if i > farthest:
return False
farthest = max(farthest, i + jump)
return True
Sign in to join the discussion
Wat stelt de greedy-variabele 'farthest' voor in het Jump Game?
Rij een circulaire route met tankstations. Bij station i krijg je gas[i] brandstof en verbruik je cost[i] om het volgende station te bereiken. Vind het startstation waarmee je het circuit kunt voltooien, of return −1.
Greedy inzicht: als totaal gas ≥ totaal kosten, bestaat er een oplossing. Houd een lopend surplus bij; zodra het onder nul zakt, moet het antwoord na dat punt beginnen.
Plan taken met een cooldown van n tussen identieke taken. Greedy: kies altijd de meest frequente resterende taak. Het antwoord hangt af van de maximale frequentie en hoeveel taken die frequentie delen.
Tasks: A A A B B C, cooldown = 2
Schedule: A B C A B _ A
Total = 7
Fractionele knapsack: je kunt fracties van items meenemen. Greedy werkt - sorteer op waarde-per-gewicht, neem de beste verhouding eerst.
0/1 knapsack: items zijn alles-of-niets. Greedy faalt hier omdat het overslaan van een zwaar-maar-waardevol item slechter kan uitpakken dan twee lichtere items meenemen. Dit vereist dynamisch programmeren.
Items: (weight=3, value=4), (weight=2, value=3), (weight=2, value=3)
Capacity: 4
Greedy (best ratio first): takes item 1 (w=3, v=4) → 1 remaining → can't fit rest → value = 4
Optimal: takes items 2+3 (w=4, v=6) → value = 6 ✗ Greedy fails!
Waarom faalt de greedy aanpak bij het 0/1 knapsack-probleem?
✅ Werkt wanneer je de greedy choice property kunt bewijzen:
❌ Faalt wanneer lokale optima geen globaal optimum vormen:
De standaardtechniek: neem aan dat er een optimale oplossing bestaat die de greedy-keuze niet maakt. Laat zien dat je één van haar keuzes kunt verwisselen met de greedy-keuze zonder de oplossing te verslechteren. Dit bewijst dat greedy minstens even goed is.
Waarvoor wordt het 'exchange argument' gebruikt?
| Aspect | Greedy | Dynamisch Programmeren | |--------|--------|------------------------| | Keuzes | Eén beste keuze per stap | Alle deelproblemen verkennen | | Heroverweegt eerder? | Nooit | Ja - slaat deelresultaten op | | Snelheid | Meestal sneller | Hangt af van de toestandsruimte | | Correctheid | Alleen als bewijsbaar | Altijd (mits correct geformuleerd) |
Bij twijfel: begin greedy - als je niet kunt bewijzen dat het werkt, schakel over naar DP.