Zeitkomplexität

Laufzeit

In a nutshell

Die Laufzeit eines Algorithmus gibt an, wie viel Zeit benötigt wird, um eine Eingabegröße zu verarbeiten, oft in Abhängigkeit von der Größe der Eingabe dargestellt. Sie dient dazu, die Effizienz und Skalierbarkeit von Algorithmen zu bewerten und zu vergleichen.

Laufzeitanalyse Beispiel

In diesem Beispiel ist der Wert von sum Äquivalent zu der Anzahl an Schritten, die der Algorithmus durchläuft
Nach der Ausführung hat sum den Wert n

LineareMethode(n)Zeit1.sum←012.for i←1 to n don+13.sum←sum+1n

Nach der Ausführung hat sum den Wert n2

QuadratischeMethode(n)Zeit1.sum←012.for i←1 to n don+13.for j←1 to n don×(n+1)4.sum←sum+1n2

Nach der Ausführung hat sum den Wert n3

KubischeMethode(n)Zeit1.sum←012.for i←1 to n don+13.for j←1 to n don×(n+1)4.for k←1 to n don2×(n+1)5.sum←sum+1n3

Größenordnungen:

Wachstum W-Ordnungen N = 1000 10N 100N 1000N
konstant 1 1 Minute 1 Minute 1 Minute 1 Minute
logarithmisch log N 1 Minute 1,3 Minuten 1,6 Minuten 2 Minuten
linear N 1 Minute 10 Minuten 2 Stunden 1 Tag
leicht überlinear N log N 1 Minute 13 Minuten 3 Stunden 1½ Tage
quadratisch N² 1 Minute 2 Stunden 5 Tage 23 Wochen
kubisch N³ 1 Minute 1 Tag 2 Jahre 2000 Jahre
exponentiell 2^N 1 Minute ∞ ∞ ∞

Fallunterscheidung

Worst-Case Analyse

Average-Case Analyse

Best-Case Analyse

Beispiel: Laufzeitanalyse von insertion sort

InsertionSort(A)Zeit1.for j←2 to length(A) don2.key←A[j]n−13.i←j−1n−14.while i>0 and A[i]>key don−1+∑tj5.A[i+1]←A[i]∑tj6.i←i−1∑tj7.A[i+1]←keyn−15n−4+3∑tj

tj: Anzahl Wiederholungen der while-Schleife bei Laufindex j

Worst-Case

T(n)=5n−4+3⋅∑j=2n(j−1)=2n−4+3⋅∑j=1nj=2n−4+3⋅n(n+1)2=3n2+7n−82

-> konstante Faktoren wenig Aussagekräftig, da hier im Beispiel gezeigt wird, dass bei steigendem n alles von 3n2 abhängt.

Asymptotische Laufzeitanalyse

O-Notation – Obere Schranke

!250

Ω-Notation – Untere Schranke

!250

Θ-Notation (Theta-Notation)

Echte obere und untere Schranke

Interpretation

"asymptotische Version" von
O ≤
Ω ≥
Θ =
o <
ω >
Ausdruck Wachstum von f Vergleich Wachstum von g
f∈o(g) Wachstum von f < Wachstum von g
f∈O(g) Wachstum von f ≤ Wachstum von g
f∈Θ(g) Wachstum von f = Wachstum von g
f∈Ω(g) Wachstum von f ≥ Wachstum von g
f∈ω(g) Wachstum von f > Wachstum von g

Mehrere Parameter & Datenstrukturen:

Laufzeitklassen

n! faktoriell
O(2n) exponentiell
O(n3) kubisch
O(n2) quadratisch (polynomiell)
O(nlog⁡(n)) super-linear
O(n) linear
O((x)) Wurzelfunktion
O(log⁡(n)) logarithmisch
O(1) beschränkt/konstant

Hierarchie

O(log⁡n)⊆O(n)⊆O(n2)⊆O(nc)⊆O(2n)
(für c≥2) (nicht vollständig)
!Laufzeitklassen Vergleich.png

Laufzeitanalyse von Sortieralgorithmen

Laufzeit elementarer Java-Strukturen (worst-case)

Struktur Operation Laufzeit
Stack (Resizing‑Array) push, pop O(1)
Queue (Ring‑Array) enqueue, dequeue O(1)
LinkedList addFirst, pollFirst O(1)
get(i), set(i), contains O(N)
PriorityQueue (Heap) add, removeMin O(log N)
ArrayList / ArrayDeque addLast amort. O(1)

(ArrayDeque meist schnellste Deque; ArrayList Einfügen mitten­drin O(N)).

Rekursionsbaum

Muster Baumhöhe Verzweigungen k Gesamtlaufzeit
T(N)=T(N−1)+c O(N) 1 Θ(N)
T(N)=T(N/2)+c O(log N) 1 Θ(log N)
T(N)=T(N−1)+T(N−2)+T(N−3)+c O(N) 3 O(3ᴺ)
T(N)=2·T(N/2)+c O(log N) 2 Θ(N)

Komplexitätsklassen

Komplexitätsklassen sind Kategorien, die Berechnungsprobleme danach gruppieren, wie viel Rechenzeit ein Algorithmus im schlimmsten Fall benötigt, um sie zu lösen, abhängig von der Größe der Eingabe.

Klasse Definition Bedeutung
P Probleme lösbar in polynomieller Zeit „praktisch“ effizient
NP Lösung prüfbar in polynomieller Zeit enthält P
NP‑schwer Jedes NP‑Problem polynomiell reduzierbar mind. so schwer wie NP
NP‑vollständig in NP und NP‑schwer härteste NP‑Probleme

Typische NP‑vollständige Probleme

∑k=0n12k=1−(1/2)n+11−12=2(1−12n+1)=2−12n.