Alle Tabs der Lerneinheit (Erklärung · Interaktiv verstehen · Praxis-Übung · Klausur-Quiz) als durchgehender Text. Ideal zum Wiederholen vor der Klausur, und für Suchmaschinen wie Google, Bing und KI-Suche (ChatGPT, Perplexity).
Erklärung
Greedy heißt 'gierig': bei jeder Entscheidung nimmst du die lokal beste Option, ohne dich umzuschauen. Manchmal landet das beim globalen Optimum, manchmal nicht. Klausur-Pflicht in 13/17 WInf-Algo-Klausuren, wichtige Counterpart-Strategie zu DP.
Die Idee in einem Satz
Greedy-Algorithmus: Trifft an jeder Stelle eine lokal optimale Entscheidung in der Hoffnung, dass die Gesamtlösung global optimal wird.
Wann funktioniert Greedy?
Zwei Voraussetzungen (analog zu DP, aber stärker):
- Greedy-Auswahl-Eigenschaft: Lokal beste Auswahl führt zur global besten Lösung
- Optimale Substruktur: Restproblem nach Greedy-Schritt hat selbe Struktur
Klausur-Faustregel: Wenn beides gilt → Greedy ist optimal. Wenn nur (2) gilt → DP nötig.
Beispiel: Münzwechsel
Problem: Gib 20€ Wechselgeld mit den wenigsten Münzen.
Münzen Euro-System: {1, 2, 5, 10, 20, 50, 100, 200}
Greedy: nimm immer die größte Münze ≤ Rest.
- 20 → 1× 20€ Münze ✓
Bei Münzen \1, 6, 10\ für 12 Cent:
- Greedy: 10 + 1 + 1 = 3 Münzen
- Optimal: 6 + 6 = 2 Münzen ✗
Greedy ist im Euro-System optimal, in beliebigen Systemen NICHT.
Klassische Greedy-Probleme
1. Activity-Selection (Klausur-Klassiker)
Gegeben Events mit Start- und Endzeit. Wähle die maximale Anzahl nicht-überlappender Events.
Greedy-Regel: Sortiere nach Endzeit. Nimm erstes Event, dann das nächste, dessen Start ≥ vorherigem End ist.
Korrekt! Beweis durch Austauschargument: wenn du eine andere Lösung hättest, könntest du das erste Event durch das mit frühester Endzeit ersetzen, ohne schlechter zu werden.
2. Huffman-Codierung
Optimale Präfix-Codes für Datenkompression. Iterativ die zwei seltensten Symbole zu einem Knoten verschmelzen → Binärbaum mit optimaler durchschnittlicher Codewort-Länge.
3. Minimum Spanning Tree (Prim, Kruskal)
Greedy auf Kanten (Kruskal: nimm immer billigste Kante ohne Zyklus) oder Knoten (Prim: erweitere Baum mit billigster Außen-Kante). Beide finden den global minimalen Spannbaum.
4. Fractional Knapsack
Wie 0/1-Knapsack, aber Items teilbar. Greedy: nimm Items in absteigender Reihenfolge nach v_i / w_i (Wert pro Gewichtseinheit), nimm so viel wie passt.
Achtung: 0/1-Knapsack (Items unteilbar) ist NICHT Greedy-lösbar, braucht DP.
5. Dijkstra
Auch ein Greedy-Algorithmus! In jedem Schritt: extrahiere Knoten mit kleinster Distanz (= lokal beste Wahl). Bei nicht-negativen Gewichten optimal.
Greedy vs. DP
| Greedy | DP | |
|---|---|---|
| Entscheidung | lokal, einmalig | global, alle Optionen geprüft |
| Speicher | O(1) oder O(n) typisch | O(n) bis O(n²) typisch |
| Laufzeit | meist O(n log n) (durch Sortierung) | meist O(n²) oder mehr |
| Optimal? | nur bei Greedy-Auswahl-Eigenschaft | immer (bei korrekter Rekurrenz) |
| Implementierung | einfacher | komplexer |
Faustregel: Erst Greedy probieren (einfacher). Wenn das nicht optimal ist (Gegenbeispiel finden!), DP nutzen.
Beweis-Strategien für Greedy-Optimalität
Austauschargument
Annahme: Es gibt eine bessere Lösung als die von Greedy. Zeige: Du kannst die Greedy-Entscheidung in die andere Lösung einbauen ohne Verschlechterung. Daraus folgt Greedy = optimal.
Greedy bleibt vorne
Bei jedem Schritt liegt die Greedy-Lösung mindestens so gut wie jede andere Teil-Lösung mit gleicher Anzahl Schritte.
Pseudocode-Schema
greedy_algorithm(input):
sort/prepare input by greedy criterion
solution = empty
for each candidate in sorted order:
if candidate is feasible:
add candidate to solution
return solution
Beispiel-Pseudocode: Activity-Selection
selectActivities(activities):
sort activities by end time ascending
selected = []
lastEnd = -infinity
for activity in activities:
if activity.start >= lastEnd:
selected.append(activity)
lastEnd = activity.end
return selected
Laufzeit: O(n log n) wegen Sortierung. Greedy-Loop selbst ist O(n).
Klausur-Faustregeln
1. Greedy = lokal beste Entscheidung. Nie zurück, nie umentscheiden.
2. Sortieren ist oft erster Schritt. Activity-Selection nach Endzeit, Knapsack nach v/w, Huffman nach Häufigkeit.
3. Greedy ist nicht immer optimal. Münzwechsel kann schiefgehen, 0/1-Knapsack braucht DP.
4. Beweise mit Austauschargument. Annehmen: andere Lösung besser → tausche greedy-Schritt rein → kein Schaden → Greedy ist optimal.
5. Greedy vs. DP: Greedy einfacher + schneller, DP optimal. Wenn unsicher: probiere Gegenbeispiele.
Häufige Stolpersteine
1. Greedy ohne Korrektheits-Beweis. Funktioniert manchmal "rein zufällig". Bei Klausur immer prüfen: gibt's ein Gegenbeispiel?
2. 0/1-Knapsack mit Greedy. Falsch! Nur Fractional Knapsack ist greedy-optimal. 0/1 (Items unteilbar) braucht DP.
3. Falsches Sortier-Kriterium. Activity-Selection nach Start-Zeit funktioniert NICHT. Muss nach Endzeit sein. Bei Knapsack: Wert pro Gewicht (v/w), nicht nur Wert.
4. Greedy für Probleme ohne Greedy-Auswahl-Eigenschaft. TSP (Traveling Salesman) ist NICHT greedy-lösbar (NP-schwer).
5. Greedy mit Backtracking verwechseln. Greedy macht eine Entscheidung pro Schritt und vergisst Alternativen. Backtracking probiert systematisch alle Möglichkeiten durch.
Interaktiv verstehen
Activity-Selection-Lab
Du hast 8 Vorlesungen mit verschiedenen Start- und Endzeiten. Wähle die maximale Anzahl, die du besuchen kannst ohne Überlappung.
Vergleich:
- Greedy nach Endzeit (korrekt!)
- Greedy nach Startzeit (Lockmittel, funktioniert nicht!)
- Greedy nach Dauer (auch falsch!)
Beobachte, welche Strategie die meisten Vorlesungen auswählt.
Interaktive Visualisierung
Interaktive Komponente: probiere sie im Topic-Player oben aus.
Klausur-Tipp: Bei Klausur-Aufgaben zur Activity-Selection IMMER nach Endzeit sortieren. Das ist die einzige korrekte Greedy-Strategie. Begründung: nach Austauschargument.
Praxis-Übung
Greedy-Algorithmen, Praxis-Übung
6 Aufgaben zu Greedy-Konzepten, klassischen Problemen, Korrektheit.
Klausurfragen mit Lösungen (6)
- F1.Was ist die Grundidee von Greedy-Algorithmen?
Antwort: Lokal beste Entscheidung treffen, ohne zurückzuschauen
Erklärung: Greedy: an jeder Stelle die LOKAL BESTE Entscheidung, ohne Alternativen zu erwägen oder zurückzusetzen. Schnell + einfach, aber nicht immer optimal.
- F2.Welche Sortierung ist korrekt für die Activity-Selection (max. nicht-überlappende Events)?
Antwort: Nach Endzeit aufsteigend
Erklärung: Nach ENDZEIT sortieren! Begründung: das Event mit frühester Endzeit lässt am meisten Raum für die folgenden Events. Beweis durch Austauschargument, Klausur-Klassiker.
- F3.Greedy findet immer das Optimum, solange das Problem eine Lösung hat.
Antwort: Falsch
Erklärung: FALSCH. Greedy findet das Optimum NUR bei Problemen mit Greedy-Auswahl-Eigenschaft. Klassisches Gegenbeispiel: 0/1-Knapsack. Greedy nach v/w sortieren funktioniert NICHT optimal bei unteilbaren Items.
Typ: Wahr/Falsch
- F4.Welche der folgenden Probleme ist KEIN klassisches Greedy-Problem?
Antwort: 0/1-Knapsack
Erklärung: 0/1-Knapsack (Items unteilbar) braucht DP, nicht Greedy. Fractional Knapsack (teilbare Items) ist greedy-optimal mit Sortierung nach v/w. Huffman + MST sind Greedy-Klassiker.
- F5.Welche Aussagen über Greedy sind RICHTIG?
Richtige Antworten: Dijkstra ist ein Greedy-Algorithmus; Greedy ist meist O(n log n) (wegen Sortierung); Activity-Selection nach Endzeit sortieren; Korrektheits-Beweise nutzen oft Austauschargument
Erklärung: Richtig: Dijkstra=Greedy, O(n log n) durch Sortierung, Endzeit für Activity-Sel., Austauschargument. Falsch: Greedy ist NICHT immer optimal (nur bei spezifischen Eigenschaften); Greedy braucht WENIGER Speicher als DP.
Typ: Multi-Select
- F6.Ordne Problem dem optimalen Algorithmus zu:
Zuordnungen:
- Fractional Knapsack → Greedy nach v/w
- 0/1-Knapsack → Dynamische Programmierung
- Activity-Selection → Greedy nach Endzeit
- Huffman-Codierung → Greedy: kleinste zwei verschmelzen
Erklärung: Klassiker-Probleme: Fractional Knapsack greedy, 0/1 DP, Activity-Selection greedy by end time, Huffman greedy bottom-up.
Typ: Zuordnung
Klausur-Quiz
Klausurfragen mit Lösungen (6)
- F1.Welches Beweis-Argument zeigt typischerweise Greedy-Optimalität?
Antwort: Austauschargument: tausche Greedy-Schritt in optimale Lösung
Erklärung: Austauschargument: Nimm an, optimale Lösung weicht in Schritt k von Greedy ab. Zeige: tausche Greedy-Wahl rein → Lösung bleibt mindestens so gut → Greedy ist optimal. Standard-Beweis-Methode.
- F2.Im Euro-Münz-System (1, 2, 5, 10, 20, 50, 100, 200 Cent) ist die Greedy-Strategie (immer größte Münze ≤ Rest) optimal.
Antwort: Wahr
Erklärung: RICHTIG. Das Euro-System ist 'kanonisch', Greedy findet das Optimum. Beweis nicht trivial (Pearson, Verma). Bei anderen Münzsystemen (z.B. {1, 6, 10}) ist Greedy nicht optimal.
Typ: Wahr/Falsch
- F3.Wann scheitert Greedy am 0/1-Knapsack?
Antwort: Wenn das beste v/w-Item zu schwer für den Rucksack ist und Kombinationen besser wären
Erklärung: Beispiel: Items (w=10, v=100, ratio=10), (w=5, v=40, ratio=8), (w=5, v=40, ratio=8). Kapazität 10. Greedy nimmt Item 1 (Wert 100). Optimal: Items 2+3 (Wert 80) NEIN, Item 1 ist besser. Anderes Beispiel: Kap=15, (w=10,v=100), (w=6,v=70), (w=4,v=60), (w=2,v=30). Greedy nach ratio (10, 11.67, 15, 15): nimmt 4+2 (v=90), 6 (Σ 12, v=160), kann nicht 10 nehmen. Optimal: 10+4+? wäre Σ14, v=160. Es ist sehr knapp aber zeigt: Greedy ist NICHT garantiert optimal bei 0/1.
- F4.Welche Laufzeit hat Activity-Selection mit Greedy nach Endzeit?
Antwort: O(n log n)
Erklärung: O(n log n), wegen der Sortierung nach Endzeit. Die Greedy-Schleife danach ist O(n). Insgesamt von Sortierung dominiert.
- F5.Greedy trifft an jeder Stelle die {{1}} beste Entscheidung. Wenn das Problem die {{2}}-Auswahl-Eigenschaft hat, ist Greedy {{3}}. Bei Activity-Selection sortiert man nach {{4}}. Beweise erfolgen oft per {{5}}-Argument.
Lösungen pro Lücke:
- {{1}}: lokal / lokal-
- {{2}}: Greedy / greedy
- {{3}}: optimal
- {{4}}: Endzeit / End
- {{5}}: Austausch / Tausch
Erklärung: Greedy-Vokabular. Lokal-beste-Wahl, Greedy-Auswahl-Eigenschaft, optimal-bei-Korrektheit, Endzeit-Sortierung, Austauschargument.
Typ: Lückentext
- F6.Sortiere: Activity-Selection mit Greedy.
Richtige Reihenfolge:
- Sortiere alle Events nach Endzeit aufsteigend
- lastEnd = -∞, selected = []
- Für jedes Event: wenn start ≥ lastEnd: nimm es
- lastEnd = aktuelles Event.end
- Liste der ausgewählten Events zurückgeben
Erklärung: Standard-Activity-Selection-Workflow. Sortierung → Init → Loop mit Konflikt-Check → lastEnd-Update → Return. Laufzeit O(n log n).
Typ: Reihenfolge