Laufzeit von Algorithmen beweisen

Laufzeit von Algorithmen beweisen

laufzeiten von Algorithmen

In diesen Artikel, gehe ich auf die Laufzeiten von Algorithmen im allgemeinen ein. Ich werde einmal erklären wie man Laufzeiten angibt und welche Besonderheiten es gibt. Diese Beschreibung von Algorithmen wird aber Plattformunabhängig sein, da man nicht den Einfluss von Hardware in dieser Angabe berücksichtigen möchte.

O-Notation

Um Laufzeiten für Algorithmen anzugeben, benutzt man die O-Notation. Mit dieser Notation kann man Grenzen angeben. Man kann zum Beispiel eine obere Grenze oder auch untere Grenze angeben. Damit legt man einfach fest, dass ein Algorithmus entweder maximal oder mindestens so viel Zeit braucht.

Diese Laufzeiten werden meistens für Algorithmen mit einer Eingabegröße von n angegeben. n Steht hier einfach für die anzahl an Problemen die gelöst werden müssen. Als Beispiel hat (vereinfacht) die Zuweisung von Variablen eine Laufzeit von genau einer Zeiteinheit. Schauen wir uns jetzt die verschiedenen Symbole und deren Bezeichnung an:

Bezeichnung Bedeutung Mathematik dahinter
O(n)Maximal n Zeitg(n) = O(f(n)) => g(n) ⪬ c*f(n)
Θ(n)Genau n Zeitg(n) = Θ(f(n)) => g(n) = c*f(n)
Ω(n)Mindestens n Zeitg(n) = Ω(f(n)) => g(n) ⪭ c*f(n)
Die wichtigsten Laufzeiten

Damit haben wir einmal die wichtigsten Bezeichnungen für die Beschreibung von Algorithmen. In der Tabelle stehen g(n) -> Zeit und f(n) -> Zeit für eine beliebige Funktion in . Das c ist eine Konstante, wobei aber gilt c > 0.

Auch wenn das c existiert kann man also sagen, dass ein Algorithmus mit der Laufzeit von 4*n trotzdem im lim(n) gegen n läuft da das c bei größer werdenden c immer weniger Einfluss hat.

Laufzeiten

In der Laufzeitanalyse gibt es bestimmte Laufzeiten, die wichtig sind bzw. oftmals auftreten. Beispiele dafür sind:

LaufzeitErklärung
Θ(1)Konstante Laufzeit
Θ(log(n))Logarithmische Laufzeit
Θ(n)Lineare Laufzeit
Θ(n log(n)Linear logarithmische Laufzeit
Θ(n2 )Quadratische Laufzeit
Θ(nn )Exponentiele Laufzeit
Θ(n!)Faktorielle Laufzeit
Beispiele für Laufzeiten

Im nächsten Kapitel beweisen wir als Beispiel einige Laufzeiten und ob sie in einer bestimmten Laufzeit enthalten sind.

Beispiele

Aufgabe 1: Beweise oder Widerlege folgende Laufzeit-Äquivalenz n3 = O(n3 -2n2 )

Lösung:

Diese Aufgabe ist eine typische Beweisaufgabe wie man sie aus der Mathematik kennt. Man kann diese Aufgabentypen mit mehreren Möglichkeiten lösen. Ich werde hier aber eine Art verwenden, die ähnlich zu Induktionsbeweisen ist.

Anleitung:

  • Ein c ∈ {c ∈ ℝ : c > 0} finden.
  • n0 finden

n3 = O(n3 -2n2 ) | Mathematische Schreibweise anwenden g(n) < c* f(n)

n3 ⪬ c*(n3 -2n2 ) | n=1

13 ⪬ c*(13 -2*12 )

1 ⪬ c*(1-2) | Umstellen

-1⪬ c | für n0 = 1 somit kein c mit den genannten Eigenschaften

________________________________________________________________________________________________________________

n3 ⪬ c*(n3 -2n2 ) | n=3

33 ⪬ c*(33 -2*32 ) | n=1

27⪬ 9c

3⪬c | c=3 gefunden bei n0 = 3

Antwort: Da wir ein konstantes c bei einen n0 = 3 finden konnten, können wir sagen, dass die Laufzeit n3 in O(n3 -2n2 ) enthalten ist. Macht soweit auch Sinn, weil wenn wir lim(n3 -2n2 ) betrachten wird 2n2 bei n gegen unendlich irgendwann keine Relevants haben und insgesammt wird die Funktion gegen n3 laufen.

Ergänzende Erklärung: n0 ist also der Zeitpunkt für den Algorithmus, wo wir ein c mit den genannten Bedingungen finde. Ab diesen Zeitpunkt ist für uns die Betrachtung der Laufzeit wichtig

Algorithmus in O(n2 )

Jetzt gehen wir mal anders dran. Man kann einerseits natürlich beweisen ob ein Algorithmus in einer bestimmten Zeit läuft aber genauso kann man auch einen Algorithmus entwickeln, der eine bestimmte Zeitvorgabe haben soll.

Aufgabe: Implementiere einen Algorithmus der in Laufzeit O(n2 ) läuft. Hierbei ist egal was der Algorithmus genau berechnet, es ist nur die Laufzeit von O(n2 ) wichtig!

Lösung:

procedure calcSomething(arr : int[])
     for i = 0 until i = arr.length do
         for j = 0 until j = arr.length do
              arr[i] = i*j

Der angegebene Algorithmus löst das Problem in quadratischer Zeit, weil wir als Eingabegröße ein Array der größe n haben. Für einen durchlauf durch das gesamte Array benötigt man somit n Zeit. Da wir dieses Array sogar verschachtelt durchgehen ergibt sich eine Laufzeit von O(n2 ) für die Schleifen. Das wird auch nicht durch die Operation im Inneren beeinflusst, weil es eine einfache Rechenoperation ist, die konstante Zeit benötigt und bei größer werdenden n eine immer geringere Gewichtung für das Gesamtergebnis hat.

Für weitere Tipps zum Entwickeln von Algorithmen habe ich hier auch noch einen anderen Artikel für dich.

Weitere Lernquellen

Hier habe ich außerdem noch ein Video von einem bekannten Youtuber, welcher das Thema auch nochmal ausführlich.

Quellen

https://de.wikipedia.org/wiki/Zeitkomplexit%C3%A4t (Besucht am 18.06.2023)

https://pixabay.com/de/vectors/laptop-infografik-online-gesch%C3%A4ft-6087062/ (Besucht am 21.06.2023)