Schreiben Sie ein Programm (oder eine Funktion), das / die je nach Ausführung vier häufig auftretende große O- Zeit-Komplexitäten aufweist. In jeder Form nimmt es eine positive ganze Zahl N an, von der Sie annehmen können, dass sie kleiner als 2 31 ist .
Wenn das Programm in seiner ursprünglichen Form ausgeführt wird, sollte es eine konstante Komplexität aufweisen. Das heißt, die Komplexität sollte Θ (1) oder äquivalent Θ (1 ^ N) sein .
Wenn das Programm umgekehrt und ausgeführt wird, sollte es eine lineare Komplexität haben. Das heißt, die Komplexität sollte Θ (N) oder äquivalent Θ (N ^ 1) sein .
(Dies macht Sinn , daN^1
wird1^N
umgekehrt.)Wenn das Programm verdoppelt , dh auf sich selbst verkettet, und führen Sie es haben sollte exponentielle Komplexität, und zwar 2 N . Das heißt, die Komplexität sollte Θ (2 ^ N) sein .
(Dies ist sinnvoll, da das2
In2^N
das Doppelte des1
In ist1^N
.)Wenn das Programm verdoppelt und umgekehrt und ausgeführt wird, sollte es eine polynomielle Komplexität aufweisen, insbesondere N 2 . Das heißt, die Komplexität sollte Θ (N ^ 2) sein .
(Dies macht Sinn , daN^2
wird2^N
umgekehrt.)
Diese vier Fälle sind die einzigen, die Sie behandeln müssen.
Beachten Sie, dass ich aus Präzisionsgründen die Big-Theta (Θ) -Notation anstelle von Big-O verwende, da die Laufzeiten Ihrer Programme sowohl oben als auch unten durch die erforderlichen Komplexitäten begrenzt sein müssen. Andernfalls würde nur das Schreiben einer Funktion in O (1) alle vier Punkte erfüllen. Es ist nicht so wichtig, die Nuance hier zu verstehen. Wenn Ihr Programm hauptsächlich k * f (N) Operationen für eine Konstante k ausführt, ist dies wahrscheinlich in Θ (f (N)).
Beispiel
Wenn das Originalprogramm wäre
ABCDE
dann sollte das Laufen eine konstante Zeit in Anspruch nehmen. Das heißt, ob der Eingang N 1 oder 2147483647 (2 31 -1) ist oder ein Wert dazwischen, er sollte ungefähr in der gleichen Zeitspanne enden.
Die umgekehrte Version des Programms
EDCBA
sollte in N. ausgedrückt lineare Zeit in Anspruch nehmen. Das heißt, die Zeit, die zum Beenden benötigt wird, sollte in etwa proportional zu N sein. N = 1 dauert also am wenigsten und N = 2147483647 dauert am meisten.
Die doppelte Version des Programms
ABCDEABCDE
Dies bedeutet, dass die Zeit, die zum Beenden benötigt wird, ungefähr proportional zu 2 N sein sollte . Wenn also N = 1 in ungefähr einer Sekunde endet, würde N = 60 länger als das Alter des Universums brauchen, um zu enden. (Nein, du musst es nicht testen.)
Die doppelte und umgekehrte Version des Programms
EDCBAEDCBA
Die Zeit, die zum Beenden benötigt wird, sollte ungefähr proportional zu N * N sein. Wenn also N = 1 in ungefähr einer Sekunde endet, würde N = 60 ungefähr eine Stunde dauern, um zu beenden.
Einzelheiten
Sie müssen zeigen oder argumentieren, dass Ihre Programme in der von Ihnen angegebenen Komplexität ausgeführt werden. Das Eingeben von Zeitdaten ist eine gute Idee, aber versuchen Sie auch zu erklären, warum die Komplexität theoretisch korrekt ist.
Es ist in Ordnung, wenn in der Praxis die Zeiten, die Ihre Programme einnehmen, nicht perfekt für ihre Komplexität (oder sogar deterministisch) repräsentativ sind. zB Eingabe N + 1 läuft manchmal schneller als N.
Die Umgebung, in der Sie Ihre Programme ausführen, spielt eine Rolle. Sie können grundlegende Annahmen darüber treffen, wie populäre Sprachen niemals absichtlich Zeit in Algorithmen verschwenden. Wenn Sie jedoch beispielsweise wissen, dass Ihre Java-Version die Blasensortierung anstelle eines schnelleren Sortieralgorithmus implementiert , sollten Sie dies berücksichtigen, wenn Sie eine Sortierung durchführen .
Bei aller Komplexität wird angenommen, dass es sich um Worst-Case-Szenarien handelt , nicht um Best-Case- oder Average-Case -Szenarien .
Die räumliche Komplexität der Programme spielt keine Rolle, nur die zeitliche Komplexität.
Die Programme können alles ausgeben. Es kommt nur darauf an, dass sie eine positive ganze Zahl N aufnehmen und die richtigen zeitlichen Komplexitäten aufweisen.
Kommentare und mehrzeilige Programme sind erlaubt. (Sie können davon ausgehen, dass dies aus
\r\n
Gründen der\r\n
Windows-Kompatibilität umgekehrt ist .)
Big O Erinnerungen
Vom schnellsten zum langsamsten O(1), O(N), O(N^2), O(2^N)
(Reihenfolge 1, 2, 4, 3 oben).
Langsamere Begriffe dominieren immer, z O(2^N + N^2 + N) = O(2^N)
.
O(k*f(N)) = O(f(N))
für konstante k. Also O(2) = O(30) = O(1)
und O(2*N) = O(0.1*N) = O(N)
.
Erinnere dich an O(N^2) != O(N^3)
und O(2^N) != O(3^N)
.
Ordentliches großes O-Spickzettel.
Wertung
Dies ist normaler Code Golf. Das kürzeste ursprüngliche Programm (die konstante Zeit eins) in Bytes gewinnt.
n = input(); for i in xrange(n): pass
hat also eine exponentielle Komplexität, weil es 2 ** k
Schritte ausführt, bei denen k = log_2(n)
die Eingabegröße ist. Sie sollten klären, ob dies der Fall ist, da sich dadurch die Anforderungen dramatisch ändern.