Skip to content

Einführung in algorithmisches Denken

Vorwort

Wie löst man Probleme effizient? Sie haben vielleicht schon folgende Erfahrung gemacht: Dasselbe Problem — der Code der einen Person liefert in wenigen Sekunden ein Ergebnis, während der einer anderen nach Minuten noch immer rechnet. Der Unterschied liegt meist im Algorithmus. Dieses Kapitel vermittelt Ihnen die Kernkonzepte algorithmischen Denkens.

Was werden Sie in diesem Artikel lernen?

Nach Abschluss dieses Kapitels werden Sie Folgendes gewonnen haben:

  • Problemaufteilungsfähigkeit: Bei komplexen Problemen an Strategien wie Teile-und-Herrsche oder Rekursion denken, anstatt sofort zu programmieren
  • Effizienzeinschätzung: Mit der O-Notation beurteilen können, welche von zwei Lösungen effizienter ist, statt auf Bauchgefühl zu vertrauen
  • Komplexitätsdenken: Vor dem Programmieren die Datenmenge und Zeitanforderungen abschätzen und die passende Algorithmusklasse wählen
  • Grundlage für weiterführendes Lernen: Basis für fortgeschrittene Datenstrukturen, verteilte Systeme und maschinelles Lernen schaffen
KapitelInhaltKernkonzepte
Kapitel 1Binäre SucheTeile-und-Herrsche, O(log n)
Kapitel 2SortieralgorithmenBubble Sort, Quick Sort, Merge Sort
Kapitel 3KomplexitätsanalyseZeitkomplexität, Platzkomplexität

0. Überblick: Was ist ein Algorithmus?

Stellen Sie sich vor, Sie suchen ein Wort in einem Wörterbuch:

  • Methode 1: Von der ersten Seite an Seite für Seite blättern (lineare Suche)
  • Methode 2: Anhand des Anfangsbuchstabens positionieren, dann binär suchen (binäre Suche)

Beide Methoden führen zum Ziel, aber die Effizienz unterscheidet sich dramatisch. Ein Algorithmus ist eine Methode zur Problemlösung.

Algorithmic Thinking: Ways to Solve ProblemsDifferent strategies fit different kinds of problems
Binary searchEliminate half each time, O(log n)
Time Complexity Quick Reference
O(1)ConstantBest, such as array access
O(log n)LogarithmicVery good, such as binary search
O(n)LinearCommon, such as traversal
O(n log n)LinearithmicAcceptable, such as quicksort
O(n²)QuadraticSlow, such as bubble sort
O(2ⁿ)ExponentialVery slow, such as brute-force recursion
Core idea:Algorithms are methods for solving problems. A good algorithm can improve efficiency by orders of magnitude. Understanding algorithmic thinking matters more than memorizing individual algorithms.

Kennzahlen eines Algorithmus:

KennzahlBedeutungWarum wichtig
ZeitkomplexitätTrend der Laufzeit bei wachsender DatenmengePerformance-Vorhersage bei großen Datenmengen
PlatzkomplexitätTrend des Speicherverbrauchs bei wachsender DatenmengeBewertung des Speicherbedarfs
KorrektheitOb stets das richtige Ergebnis geliefert wirdGrundvoraussetzung eines Algorithmus

📊 Zeile für Zeile erklärt

Zeitkomplexität: Wird mit der O-Notation beschrieben. O(n) bedeutet: Verdoppelt sich die Datenmenge, verdoppelt sich die Zeit; O(n²) bedeutet: Verdoppelt sich die Datenmenge, vervierfacht sich die Zeit.

Platzkomplexität: Ebenfalls in O-Notation. Manche Algorithmen tauschen Platz gegen Zeit (z. B. Hashtabellen), andere Zeit gegen Platz (z. B. Kompressionsalgorithmen).

Korrektheit: Ein Algorithmus muss für alle möglichen Eingaben korrekte Ergebnisse liefern. Randbedingungen (leere Eingabe, extrem große Eingabe) sind am fehleranfälligsten.


1. Binäre Suche: Jedes Mal die Hälfte ausschließen

1.1 Prinzip der binären Suche

💡 Wie funktioniert die binäre Suche?

Voraussetzung: Die Daten müssen sortiert sein

Ablauf:

  1. Das mittlere Element finden
  2. Wenn das mittlere Element dem Ziel entspricht — gefunden!
  3. Wenn das Ziel kleiner als das mittlere Element ist, im linken Teil weitersuchen
  4. Wenn das Ziel größer als das mittlere Element ist, im rechten Teil weitersuchen
  5. Jedes Mal die Hälfte ausschließen, bis gefunden oder Nicht-Existenz bestätigt ist

Zeitkomplexität: O(log n)

Alltagsanalogie: Zahlenratespiel. Ich denke mir eine Zahl zwischen 1 und 100, Sie raten jedes Mal die Mitte und ich sage, ob sie zu groß oder zu klein ist. Nach höchstens 7 Versuchen haben Sie die Zahl (da 2⁷ = 128 > 100).

👇 Probieren Sie es selbst: Die folgende Demo zeigt das Funktionsprinzip der binären Suche. Wählen Sie zwischen sequenzieller und binärer Suche, um zu vergleichen:

Search AlgorithmsHow to find a target in data
Linear search: check items one by one
3
7
2
9
5
1
8
4
6
10
Target number:
Time complexity: O(n)
Use case: unordered arrays
Performance Comparison
Data sizeLinear searchBinary search
10At most 10 stepsAt most 4 steps
100At most 100 stepsAt most 7 steps
1000At most 1000 stepsAt most 10 steps
10000At most 10000 stepsAt most 14 steps

1.2 Warum ist die binäre Suche so schnell?

DatenmengeLineare SucheBinäre Suche
100100 Vergleiche7 Vergleiche
1.0001.000 Vergleiche10 Vergleiche
1.000.0001.000.000 Vergleiche20 Vergleiche
1.000.000.0001.000.000.000 Vergleiche30 Vergleiche

📊 Zeile für Zeile erklärt

Erste Spalte (Datenmenge): Wie viele Daten durchsucht werden. Die Datenmenge wächst von 100 auf 1 Milliarde (eine Verzehnfachung um das Millionenfache!)

Zweite Spalte (lineare Suche): Die „dümmste" Methode — vom ersten Element an einzeln suchen. Die Anzahl der Vergleiche entspricht der Datenmenge; je mehr Daten, desto mehr Vergleiche.

Dritte Spalte (binäre Suche): Die clevere Methode — jedes Mal die Hälfte ausschließen. Die Anzahl der Vergleiche hängt nur vom Logarithmus der Datenmenge ab. Selbst bei 1 Milliarde Datensätzen sind nur 30 Vergleiche nötig!

Vergleichsfazit: Bei 1 Million Datensätzen benötigt die lineare Suche 1 Million Vergleiche, die binäre Suche nur 20 — ein Unterschied vom Faktor 50.000!

📊 Die Macht des logarithmischen Wachstums

Die Zeitkomplexität der binären Suche ist O(log n). Das bedeutet:

  • 1 Milliarde Daten — höchstens 30 Vergleiche
  • 1 Billion Daten — höchstens 40 Vergleiche

Das ist die Macht des logarithmischen Wachstums: Die Datenmenge wächst um das 1000-fache, aber die Anzahl der Vergleiche steigt nur um 10.


2. Sortieren: Aus Unordnung wird Ordnung

2.1 Gängige Sortieralgorithmen

AlgorithmusZeitkomplexitätMerkmaleAnwendungsbereich
Bubble SortO(n²)Einfach, aber langsamLehre, kleine Datenmengen
Selection SortO(n²)Einfach, aber langsamKleine Datenmengen
Insertion SortO(n²)Schnell bei nahezu sortierten DatenKleine Datenmengen, nahezu sortiert
Quick SortO(n log n)In der Praxis am schnellstenAllgemeines Sortieren
Merge SortO(n log n)Stabiles SortierenSzenarien, die Stabilität erfordern
Heap SortO(n log n)In-place SortierungSpeicherbegrenzte Szenarien

📊 Zeile für Zeile erklärt

Bubble Sort: Der grundlegendste Sortieralgorithmus, wie Luftblasen, die im Wasser aufsteigen. Leicht verständlich, aber am langsamsten. Geeignet zum Erlernen des Sortierkonzepts, nicht für den praktischen Einsatz.

Selection Sort: Jedes Mal das kleinste Element auswählen und nach vorne stellen. Ebenfalls einfach, aber unabhängig davon, ob die Daten bereits sortiert sind, immer gleich viele Vergleiche.

Insertion Sort: Wie beim Sortieren von Handkarten. Jedes Element wird in den bereits sortierten vorderen Teil eingefügt. Sehr effizient bei nahezu sortierten Daten.

Quick Sort: Der in der Praxis am häufigsten verwendete Sortieralgorithmus. Im Durchschnitt am schnellsten, verschlechtert sich aber im schlechtesten Fall (bereits sortierte Daten) auf O(n²).

Merge Sort: Basiert auf dem „Teile-und-Herrsche"-Prinzip, immer O(n log n), benötigt aber zusätzlichen Speicherplatz. Geeignet, wenn stabiles Sortieren erforderlich ist.

Heap Sort: Nutzt die Heap-Datenstruktur zum Sortieren, in-place (kein zusätzlicher Speicherplatz), aber in der Praxis oft langsamer als Quick Sort.

2.2 Warum ist Quick Sort „schnell"?

💡 Prinzip von Quick Sort

Kernidee: Teile-und-Herrsche-Methode

  1. Ein „Pivot"-Element auswählen
  2. Kleinere Elemente als das Pivot nach links, größere nach rechts
  3. Den linken und rechten Teil jeweils rekursiv sortieren
  4. Ergebnisse zusammenführen

Warum schnell?

  • Nach jeder Partitionierung steht das Pivot-Element an seiner endgültigen Position
  • Im Durchschnitt wird bei jeder Partition etwa die Hälfte der Elemente ausgeschlossen
  • Zeitkomplexität O(n log n)

Alltagsanalogie: Bücherregal aufräumen. Ein Buch herausziehen, dünnere nach links, dickere nach rechts legen. Dann den Prozess für beide Stapel wiederholen.

👇 Probieren Sie es selbst: Die folgende Demo visualisiert Sortieralgorithmen. Erzeugen Sie ein Array und beobachten Sie den Vergleich zwischen Bubble Sort und Quick Sort:

Sorting AlgorithmsPut data into order
50
30
70
40
90
20
60
80
10
55
Choose a sorting algorithm
Select a sorting algorithm to start the demo
Time complexity:
Algorithm Comparison
AlgorithmAverage timeWorst timeSpaceStable
Bubble sortO(n²)O(n²)O(1)
Quick sortO(n log n)O(n²)O(log n)
Merge sortO(n log n)O(n log n)O(n)
Insertion sortO(n²)O(n²)O(1)

3. Rekursion: Sich selbst aufrufen

3.1 Die Essenz der Rekursion

💡 Was ist Rekursion?

Rekursion ist eine Programmiertechnik, bei der eine Funktion sich selbst aufruft.

Zwei Schlüsselelemente:

  1. Basisfall: Wann wird die Rekursion beendet?
  2. Rekursionsschritt: Wie wird das Problem in kleinere Teilprobleme zerlegt?

Klassisches Beispiel: Fakultät

js
function factorial(n) {
  if (n <= 1) return 1        // Basisfall
  return n * factorial(n - 1) // Rekursionsschritt
}

Alltagsanalogie: Russische Matrjoschka-Puppen. Eine Puppe öffnen, darin ist eine kleinere, bis zur kleinsten, die sich nicht mehr öffnen lässt.

3.2 Rekursion vs. Iteration

EigenschaftRekursionIteration (Schleife)
Code-KnappheitMeist knapperMöglicherweise komplexer
SpeicherverbrauchHöher (Aufrufstapel)Niedriger
PerformanceEtwas langsamer (Funktionsaufruf-Overhead)Schneller
AnwendungsbereichBaumtraversierung, Teile-und-HerrscheEinfache Wiederholungsaufgaben

📊 Zeile für Zeile erklärt

Code-Knappheit: Rekursion kann komplexe Logik oft in wenigen Zeilen ausdrücken (z. B. Baumtraversierung), während Schleifen mehr Variablen und Verschachtelungen benötigen können.

Speicherverbrauch: Rekursion verwendet einen „Aufrufstapel", um die Informationen jeder Ebene zu speichern — wie das Stapeln von Tellern. Bei jedem Rekursionsschritt kommt ein Teller hinzu. Schleifen benötigen diesen Overhead nicht.

Performance: Jeder Funktionsaufruf hat einen Overhead (Parameterübergabe, Stapeloperationen etc.), daher ist Rekursion in der Regel etwas langsamer als Schleifen.

Anwendungsbereich: Rekursion eignet sich für Probleme mit intrinsisch rekursiver Struktur (z. B. Dateibäume, DOM-Bäume); Schleifen für einfache Wiederholungsoperationen (z. B. Array-Traversierung).

⚠️ Fallen der Rekursion

Stapelüberlauf (Stack Overflow): Die Rekursionstiefe ist zu groß, der Aufrufstapel wird erschöpft.

Lösungen:

  • Auf Iteration umstellen
  • Endrekursionsoptimierung verwenden (von einigen Sprachen unterstützt)
  • Rekursionstiefe begrenzen

👇 Probieren Sie es selbst: Die folgende Demo zeigt den Aufrufprozess der Rekursion. Beobachten Sie, wie eine Funktion sich selbst aufruft:

Recursive Thinking: A Function Calls ItselfBreak a large problem into smaller problems of the same kind
🪆
Nested dolls
Open a large doll and there is a smaller doll inside
Open that one and there is an even smaller one, until the smallest case
That is recursion.
Recursive examples
Factorial: n! = n × (n-1)!
5! = 5 × 4!
4! = 4 × 3!
3! = 3 × 2!
2! = 2 × 1!
1! = 1 (base case)
↑ return 1
↑ return 2 × 1 = 2
↑ return 3 × 2 = 6
↑ return 4 × 6 = 24
↑ return 5 × 24 = 120
Three Elements of Recursion
1
Base case
When should recursion stop? There must be a termination condition.
Example: 1! = 1
2
Recursive call
How does the problem get smaller? Call the same function on a smaller case.
Example: turn n! into (n-1)!
3
Return result
How does the current problem use the result of the subproblem?
Example: the result of n × (n-1)!
✓ Pros
  • Concise code
  • Naturally expresses recursive structures
  • Good for tree and graph traversal
✗ Cons
  • May repeat work
  • Uses stack space
  • Can be harder to debug

4. Greedy-Algorithmen: In jedem Schritt das Optimum wählen

4.1 Das Greedy-Prinzip

💡 Was ist ein Greedy-Algorithmus?

Greedy-Algorithmen wählen in jedem Schritt die aktuell optimal erscheinende Entscheidung in der Hoffnung, dadurch eine global optimale Lösung zu finden.

Anwendungsbedingungen:

  1. Greedy-Eigenschaft: Lokale Optima führen zu globalen Optima
  2. Optimale Teilstruktur: Die optimale Lösung des Problems enthält die optimalen Lösungen der Teilprobleme

Klassisches Beispiel: Münzwechsel

  • Ziel: Einen bestimmten Betrag mit möglichst wenigen Münzen bilden
  • Greedy-Strategie: Jedes Mal die größte Münze wählen
  • Ergebnis: 67 € = 50 + 10 + 5 + 1 + 1 (5 Münzen)

Alltagsanalogie: Beim Bergaufsteigen jedes Mal den steilsten Weg wählen. Man erreicht zwar nicht unbedingt den höchsten Gipfel, aber meistens eine gute Position.

4.2 Grenzen des Greedy-Ansatzes

⚠️ Greedy liefert nicht immer die optimale Lösung

Gegenbeispiel: Münzwechsel

Wenn die Münzwerte [1, 3, 4] sind und 6 € gebildet werden sollen:

  • Greedy: 4 + 1 + 1 = 3 Münzen
  • Optimal: 3 + 3 = 2 Münzen

Der Greedy-Algorithmus ist hier gescheitert!

Lerneffekt: Greedy-Algorithmen sind einfach und effizient, führen aber nicht immer zur optimalen Lösung. Vor der Anwendung muss bewiesen werden, dass das Problem die Greedy-Bedingungen erfüllt.

👇 Probieren Sie es selbst: Die folgende Demo zeigt die praktische Wirkung von Greedy-Algorithmen. Probieren Sie verschiedene Münzkombinationen und beobachten Sie die Leistung der Greedy-Strategie:

Greedy Algorithms: Choose the Best Current MoveLocal optimum → global optimum?
A greedy algorithm chooses the best option available at each step
It hopes a series of local choices reaches a global optimum
Classic problems
Coin Change Problem
Change needed: 37
20
× 1 = 20
10
× 1 = 10
5
× 1 = 5
1
× 2 = 2
Needs 5 coins total
✓ Greedy strategy: choose the largest coin each time
✓ Works for currencies such as RMB and USD
Greedy vs Dynamic Programming
FeatureGreedy algorithmDynamic programming
Decision styleChoose the current best each stepConsider all possibilities and choose the best
OptimalityMay not be globally optimalGuarantees a global optimum
Time complexityO(n) or O(n log n)O(n²) or higher
Best fitLocal optimum → global optimumOverlapping subproblems
✓ Pros
  • Simple to implement
  • Efficient
  • Low space complexity
✗ Cons
  • Does not always guarantee a global optimum
  • Limited applicability
  • Requires an optimality proof

5. Algorithmus-Entwurfsparadigmen

ParadigmaIdeeTypische AlgorithmenAnwendbare Probleme
Teile-und-HerrscheProblem in kleinere Probleme zerlegenQuick Sort, Merge SortZerlegbare Probleme
GreedyJeden Schritt optimal wählenMinimaler Spannbaum, Huffman-KodierungProbleme mit Greedy-Eigenschaft
Dynamische ProgrammierungLösungen von Teilproblemen speichernRucksackproblem, Kürzester PfadÜberlappende Teilprobleme
BacktrackingAusprobieren, bei Sackgasse zurückgehenAcht-Damen, Alle PermutationenSuchprobleme

📊 Zeile für Zeile erklärt

Teile-und-Herrsche: Große Probleme in kleine zerlegen, einzeln lösen und dann zusammenführen. Wie beim Aufräumen: Wohnzimmer, Schlafzimmer und Küche getrennt putzen, am Ende ist alles sauber.

Greedy: Jeden Schritt das aktuell Beste wählen, ohne langfristige Konsequenzen zu bedenken. Wie beim Essen zuerst das Lieblingsgericht zu wählen — vielleicht nicht die optimale Essensreihenfolge, aber schnell.

Dynamische Programmierung: Zwischenergebnisse merken, um Doppelberechnungen zu vermeiden. Wie sich Notizen machen: Beim nächsten Mal dasselbe Problem einfach nachschlagen, ohne es neu zu lösen.

Backtracking: Wenn es nicht weitergeht, zurückkehren und es anders versuchen. Wie in einem Labyrinth: Dieser Weg ist versperrt — zurück zur letzten Kreuzung und einen anderen probieren.

👇 Probieren Sie es selbst: Die folgende Demo zeigt die Merkmale und Anwendungsbereiche verschiedener Algorithmus-Entwurfsparadigmen:

Algorithm Design ParadigmsCommon patterns for solving problems
Algorithm design paradigms are general strategies for solving problems. Learning them helps you find solution ideas quickly.
✂️
Divide and conquer
Divide, solve, combine
📊
Dynamic programming
Store results to avoid repetition
🎯
Greedy
Local optimum
🔙
Backtracking
Try and retreat
✂️Divide and conquer
Core idea
Split a large problem into smaller independent problems, solve them recursively, then combine the results.
Use cases
Array sortingMatrix multiplicationLarge integer arithmetic
Classic problems
📝
Merge sort
📝
Quick sort
📝
Binary search
📝
Strassen matrix multiplication
Time complexity
O(n log n)
Often much faster than brute force
Paradigm Comparison
ParadigmCore strategyOptimalityUse case
✂️ Divide and conquerSplit → recurse → combineGuarantees optimumProblems that split independently
📊 Dynamic programmingStore subproblem answersGuarantees optimumOverlapping subproblems
🎯 GreedyChoose the best each timeNot always optimalLocal optimum → global optimum
🔙 BacktrackingDepth-first searchGuarantees optimumSmall search spaces that need enumeration
How to choose the right paradigm?
1
Analyze problem features
Are there overlapping subproblems? Is there optimal substructure?
2
Decide whether an optimum is required
Greedy is not always optimal; dynamic programming guarantees an optimum.
3
Consider input size
Backtracking fits small inputs, while divide and conquer fits larger inputs.

6. Zusammenfassung: Algorithmen als Kunst des Problemlösens

Lassen Sie uns die verschiedenen algorithmischen Denkweisen mit einer Analogie zusammenfassen:

DenkweiseAnalogieKernpunkt
Binäre SucheZahlenratenJedes Mal die Hälfte ausschließen
SortierenBücherregal aufräumenOrdnung schaffen
RekursionMatrjoschka-PuppenGroßes klein machen
GreedyBergauf den Weg wählenLokales Optimum

💡 Kernbotschaft

Die Essenz von Algorithmen ist die Balance zwischen „Effizienz" und „Korrektheit".

  • Ein guter Algorithmus kann die Programmeffizienz um Größenordnungen steigern
  • Überoptimierung kann jedoch zu unnötiger Komplexität führen
  • Erst Korrektheit sicherstellen, dann Effizienz anstreben

Algorithmisches Denken zu verstehen ist wichtiger als spezifische Algorithmen zu memorieren:

  • Teile-und-Herrsche: Große Probleme in kleine zerlegen
  • Greedy: Jeden Schritt optimal wählen
  • Dynamische Programmierung: Teilproblemlösungen speichern
  • Backtracking: Ausprobieren, bei Sackgasse zurückkehren

Weiterführende Literatur

  • Introduction to Algorithms: Klassisches Lehrbuch für systematisches Algorithmus-Lernen
  • LeetCode: Algorithmusfähigkeiten durch Übungsaufgaben verbessern
  • Algorithmus-Visualisierung: Ausführung von Algorithmen intuitiv verstehen
  • Wettbewerbs-Algorithmen: Fortgeschrittene Algorithmus-Techniken erlernen