Ist dies technisch ein O (1) -Algorithmus für "Hello World"?

117

Würde dies als O (1) -Algorithmus für "Hallo Welt!" ??

public class Hello1
{
   public static void Main()
   {
      DateTime TwentyYearsLater = new DateTime(2035,01,01);
      while ( DateTime.Now < TwentyYearsLater )
      { 
          System.Console.WriteLine("It's still not time to print the hello ...");
      }
      System.Console.WriteLine("Hello, World!");
   }
}

Ich denke darüber nach, die zu verwenden

DateTime TwentyYearsLater = new DateTime(2035,01,01);
while ( DateTime.Now < TwentyYearsLater )
{ 
   // ... 
}

Codeausschnitt als Besetztschleife, die als Witz eingefügt werden kann, wenn jemand nach einem Algorithmus einer bestimmten Komplexität fragt. Wäre das richtig?

Subpar Web Dev
quelle
15
Dies ist O(N)keine KomplexitätO(1)
Fabjan
19
@SubparWebDev Nein, Sie wissen nicht, wie oft die Schleife durchlaufen wird, selbst wenn Sie den genauen Zeitunterschied zwischen dem Start des Programms und dem angegebenen Datum kennen. Es hängt davon ab, wie schnell der Computer läuft, was noch darauf läuft, wie die CPU die Aufgabe
plant
131
@Fabjan Es gibt keine N, von denen der Algorithmus abhängig ist, daher kann man nicht sagen, dass es sich um einen O (N) -Algorithmus handelt.
Servy
29
Technisch gibt es keine Eingabe, Nmacht also nicht einmal Sinn. Sie können jedoch DateTime.Noweine Eingabe in Betracht ziehen , die dies immer noch vom Ergebnis abhängig macht. Wenn Sie einen realistischen Wert für annehmen können DateTime.Now, dann wiederholt das Programm eine konstante Anzahl von Malen.
Poke
43
Die Problemstellung muss definieren, was N ist.
Yacoub Massad

Antworten:

406

Die Big O-Notation wird in diesem Zusammenhang verwendet, um eine Beziehung zwischen der Größe der Eingabe einer Funktion und der Anzahl der Operationen zu beschreiben, die ausgeführt werden müssen, um das Ergebnis für diese Eingabe zu berechnen.

Ihre Operation hat keine Eingabe, auf die sich die Ausgabe beziehen kann, daher ist die Verwendung der Big O-Notation unsinnig. Die Zeit, die die Operation benötigt, ist unabhängig von den Eingaben der Operation (dh ... keine). Da ist keine Beziehung zwischen dem Eingang und der Anzahl von Operationen durchgeführt, können Sie Big O nicht , dass nicht vorhandene Beziehung zu beschreiben ,

Servieren
quelle
6
Was ist mit O(max(1, 2035 - yearTheProgramIsStarted))?
Bergi
19
@Bergi [Eigentlich nein [( stackoverflow.com/questions/34048740/… ), Sie können die Anzahl der Iterationen der Schleife nicht einfach anhand der Zeit beschreiben, zu der Sie den Job ausführen. Und natürlich kombinieren Sie dies mit der Tatsache, dass die Systemuhr vom Benutzer jederzeit auf eine beliebige Zeit usw. geändert werden kann usw. und Sie immer noch keine wohlgeformte Eingabe haben, die genau mit einer Reihe von verknüpft werden kann Operationen, die zur Erzeugung der Ausgabe erforderlich sind. Selbst die Ausgabe selbst ist nicht konsistent.
Servy
23
Man könnte argumentieren, dass der Zustand des Systems (einschließlich der Uhr) Teil der Eingabe für das Programm ist. In diesem Sinne können Sie das Datum als Eingabeparameter verwenden, wenn auch nicht explizit. Es ist jedoch seltsam.
Connor Clark
9
Um klarer zu sein, ist die "implizite" Eingabe das Delta zwischen dem 1. Januar 2035 und heute.
Connor Clark
6
@Hoten Aber die Systemzeit ist kein fester Wert. Diese Funktion ist nicht gleichbedeutend mit dem Akzeptieren von a DateTimefür die Startzeit als Eingabe. Wie ich bereits sagte, kann sich die Systemuhr im Laufe der Zeit ändern . Auch hier können Sie die von Ihnen beschriebene Quazi-Eingabe nicht direkt einer festen Ausgabe zuordnen. Es ist keine bekannte Anzahl von Vorgängen für eine bestimmte Startzeit oder sogar für zwei Programme bekannt, die immer einen vernünftigen Wert von erhalten DateTime.Now. Sie können die beiden also nicht in Beziehung setzen, wenn sich die Zeit ändert, da Sie sie nicht einmal in Beziehung setzen können, wenn Die Zeit ändert sich nicht .
Servy
88

Big-O-Notation bedeutet ungefähr "bei einer Operation mit einem Arbeitsaufwand N, wie viel Rechenzeit, proportional zu N, benötigt der Algorithmus?". Zum Beispiel kann das Sortieren eines Arrays der Größe N N ^ 2, Nlog (N) usw. dauern.

Dies hat keine Menge an Eingabedaten, auf die reagiert werden kann. Also ist es nicht O(anything).

Noch schlimmer; Dies ist technisch gesehen kein Algorithmus. Ein Algorithmus ist eine Methode zur Berechnung des Werts einer mathematischen Funktion. Mathematikfunktionen sind eine Zuordnung von einer Eingabe zu einer Ausgabe. Da dies keine Eingabe erfordert und nichts zurückgibt, ist es keine Funktion im mathematischen Sinne. Aus Wikipedia:

Ein Algorithmus ist eine effektive Methode, die innerhalb einer begrenzten Menge von Raum und Zeit und in einer genau definierten formalen Sprache zur Berechnung einer Funktion ausgedrückt werden kann. Ausgehend von einem Anfangszustand und einer Anfangseingabe (möglicherweise leer) beschreiben die Anweisungen eine Berechnung, die bei Ausführung eine endliche Anzahl genau definierter aufeinanderfolgender Zustände durchläuft, schließlich eine "Ausgabe" erzeugt und an einem Endzustand endet.

Was dies technisch ist, ist ein Steuerungssystem. Aus Wikipedia;

Ein Steuerungssystem ist ein Gerät oder eine Gruppe von Geräten, die das Verhalten anderer Geräte oder Systeme verwalten, steuern, steuern oder regulieren.

Für Leute, die eine detailliertere Antwort auf den Unterschied zwischen mathematischen Funktionen und Algorithmen und die leistungsfähigeren Fähigkeiten von Computern wünschen, um nebensächliche Dinge wie Konsolenausgabe, Anzeige von Grafiken oder Steuerung von Robotern zu tun, gibt es eine lesen Sie dieses Dokument auf der Starke kirchliche Hypothese

Abstrakt

Die klassische Sichtweise der Berechnung von Berechnungspositionen als Closed-Box-Transformation von Eingaben (rationale Zahlen oder endliche Zeichenfolgen) in Ausgaben. Nach der interaktiven Sichtweise des Rechnens ist die Berechnung eher ein fortlaufender interaktiver Prozess als eine funktionsbasierte Umwandlung einer Eingabe in eine Ausgabe. Insbesondere erfolgt die Kommunikation mit der Außenwelt während der Berechnung, nicht davor oder danach. Dieser Ansatz verändert unser Verständnis davon, was Berechnung ist und wie sie modelliert wird, radikal.

Die Akzeptanz der Interaktion als neues Paradigma wird durch die Strong Church-Turing Thesis (SCT) behindert, die weit verbreitete Überzeugung, dass Turing Machines (TMs) alle Berechnungen erfassen, sodass Rechenmodelle, die aussagekräftiger sind als TMs, unmöglich sind. In diesem Artikel zeigen wir, dass SCT die ursprüngliche Church-Turing-These (CTT) auf eine Weise neu interpretiert, die Turing nie beabsichtigt hatte. seine allgemein angenommene Gleichwertigkeit mit dem Original ist ein Mythos. Wir identifizieren und analysieren die historischen Gründe für den weit verbreiteten Glauben an SCT. Nur wenn wir akzeptieren, dass es falsch ist, können wir beginnen, Interaktion als alternatives Paradigma der Berechnung zu übernehmen

Steve Cooper
quelle
Es muss keine Sequenz sein. Es handelt sich nur um eine Dateneingabe, und die Landau-Notation beschreibt die Laufzeit in Bezug auf einige Metriken für diese Daten - normalerweise etwas größenbezogenes.
Bergi
@Bergi - ja, sehen Sie Ihren Punkt! Eigentlich nur eine Annäherung, aber ja - wenn Sie den Arbeitsaufwand und die Anzahl der Schritte messen können, die erforderlich sind, um dorthin zu gelangen, spiegelt big-o die Beziehung dieser beiden Maßnahmen wider. Näher?
Steve Cooper
@kapep - es ist keine reine Funktion, weil es eine void-Methode ist, aber wenn wir die Konsolenausgabe zählen, ist es immer noch zufällig; es könnte jedes von {"Hallo, Welt!", "Es ist immer noch nicht Zeit, das Hallo zu drucken ... \ nHallo, Welt!", "Es ist immer noch nicht Zeit, das Hallo zu drucken ... Es ist immer noch nicht Zeit zum Drucken Hallo ... \ nHallo, Welt! ", ...}
Steve Cooper
1
Drucken auf Standard ist keine Ausgabe?
RPax
4
@rpax Nicht mathematisch, nein. Eine Funktion ist eine unveränderliche Übersetzung von Eingaben zu Ausgaben. Beispiel: 'Quadrat' ist die Funktion, die bei Eingabe von 3 immer 9 zurückgibt. Eine c # -Methode ist nur dann eine mathematische Funktion, wenn ein Aufruf mit denselben Parametern immer denselben Rückgabewert liefert. Andernfalls - wenn es Nebenwirkungen wie das Schreiben auf die Konsole, das Anzeigen von Grafiken und das Zuweisen von Speicher hat - sind dies keine mathematischen Funktionen. (Ich werde einen Link zu meiner Antwort hinzufügen, der in unerträglichen Details darauf eingeht :))
Steve Cooper
41

Nein, Ihr Code hat eine zeitliche Komplexität von O(2^|<DeltaTime>|) ,

Für eine korrekte Codierung der aktuellen Zeit.
Bitte, lassen Sie mich zuerst für mein Englisch entschuldigen.

Was ist und wie funktioniert Big O in CS?

Die Big O-Notation wird nicht verwendet, um die Eingabe eines Programms mit seiner Laufzeit zu verknüpfen .
Die Big-O-Notation ist eine Möglichkeit, das asymptotische Verhältnis zweier Größen auszudrücken .

Bei der Algorithmusanalyse sind diese beiden Größen nicht die Eingabe (für die man zuerst eine "Mess" -Funktion haben muss) und die Laufzeit.
Sie sind die Länge der Codierung einer Instanz des Problems 1 und eine interessierende Metrik.

Die am häufigsten verwendeten Metriken sind

  1. Die Anzahl der Schritte, die erforderlich sind, um den Algorithmus in einem bestimmten Berechnungsmodell zu vervollständigen.
  2. Der Platz, den das Berechnungsmodell benötigt, wenn ein solches Konzept vorhanden ist.

Implizit ist eine TM als Modell angenommen , so dass der erste Punkt zur übersetzten Anzahl von Anwendungen der Übergang 2 - Funktion , dh „Stufen“, und die zweiter übersetzt die Anzahl der verschiedenen Band Zellen mindestens einmal geschrieben .

Wird auch oft implizit angenommen, dass wir anstelle der ursprünglichen Codierung eine polynomiell verwandte Codierung verwenden können, beispielsweise ist eine Funktion, die ein Array von Anfang bis Ende durchsucht, O(n)komplex, obwohl eine Codierung einer Instanz eines solchen Arrays eine Länge von haben sollte n*b+(n-1)wo bist die (konstante) Anzahl von Symbolen jedes Elements. Dies liegt daran, bdass eine Konstante des Berechnungsmodells und damit der Ausdruck über und betrachtet wirdn asymptotisch gleich ist.

Dies erklärt auch, warum ein Algorithmus wie die Trial Division ein exponentieller Algorithmus ist, obwohl er im Wesentlichen ein for(i=2; i<=sqr(N); i++)ähnlicher Algorithmus 3 ist .

Sehen Sie das .

Dies bedeutet auch, dass die Big-O-Notation möglicherweise so viele Parameter verwendet, wie zur Beschreibung des Problems erforderlich sind. Ist es nicht ungewöhnlich, dass für einige Algorithmen ein k- Parameter vorhanden ist?

Es geht also nicht um die "Eingabe" oder "es gibt keine Eingabe".

Studienfall jetzt

Die Big O-Notation stellt Ihren Algorithmus nicht in Frage, sondern setzt lediglich voraus, dass Sie wissen, was Sie tun. Es ist im Wesentlichen ein Werkzeug, das überall anwendbar ist, selbst für Algorithmen, die absichtlich schwierig sein können (wie bei Ihnen).

Um Ihr Problem zu lösen, haben Sie das aktuelle und ein zukünftiges Datum verwendet. Sie müssen also irgendwie Teil des Problems sein. Einfach ausgedrückt: Sie sind Teil der Instanz des Problems.

Insbesondere lautet die Instanz:

<DeltaTime>

Wo das <>bedeutet, eine nicht pathologische Kodierung der Wahl.

Siehe unten für sehr wichtige Erläuterungen.

Ihre große O-Komplexitätszeit ist also nur O(2^|<DeltaTime>|)deshalb so , weil Sie eine Reihe von Iterationen durchführen, die vom Wert der aktuellen Zeit abhängen. Es macht keinen Sinn, andere numerische Konstanten zu setzen, da die asymptotische Notation nützlich ist, da sie Konstanten eliminiert (so ist beispielsweise die Verwendung von O(10^|<DeltaTime>|*any_time_unit)sinnlos).

Wo der schwierige Teil ist

Wir haben oben eine wichtige Annahme getroffen: dass das Berechnungsmodell 5- mal reifiziert , und mit Zeit meine ich die (reale?) Physikalische Zeit. Es gibt kein solches Konzept im Standard-Rechenmodell, ein TM kennt die Zeit nicht, wir verknüpfen die Zeit mit der Anzahl der Schritte, weil unsere Realität so funktioniert 4 .

In Ihrem Modell können Sie jedoch die Terminologie funktionaler Personen verwenden, indem Sie sagen, dass Main nicht rein ist, das Konzept jedoch dasselbe.

Um dies zu verstehen, sollte man beachten, dass nichts das Framework daran hindert, eine gefälschte Zeit zu verwenden, die zweimal, fünf, zehnmal schneller als die physische Zeit läuft. Auf diese Weise wird Ihr Code in "der Hälfte", "einem Fünftel", "einem Zehntel" der "Zeit" ausgeführt.

Diese Reflexion ist wichtig für die Auswahl der Codierung von <DeltaTime>. Dies ist im Wesentlichen eine komprimierte Schreibweise <(CurrentTime, TimeInFuture)>. Da im Priorat keine Zeit vorhanden ist, könnte die Codierung von CurrentTime sehr gut das Wort Now (oder eine andere Wahl) am Vortag sein, das als Yesterday codiert werden könnte , indem die Annahme gebrochen wird, dass die Länge der Codierung zunimmt mit der physischen Zeit geht vorwärts (und der von DeltaTime nimmt ab)

Wir müssen die Zeit in unserem Rechenmodell richtig modellieren, um etwas Nützliches zu tun.

Die einzig sichere Wahl, die wir treffen können, besteht darin, Zeitstempel mit zunehmender Länge zu codieren (aber immer noch nicht unär zu verwenden), wenn die physische Zeit voranschreitet. Dies ist die einzig wahre Eigenschaft der Zeit, die wir brauchen, und diejenige, die die Codierung abfangen muss. Nur mit dieser Art der Codierung kann Ihr Algorithmus eine zeitliche Komplexität erhalten.

Ihre Verwirrung, falls vorhanden, ergibt sich aus der Tatsache, dass das Wort Zeit in den Sätzen "Was ist seine zeitliche Komplexität?" und 'Wie viel Zeit wird es dauern?' bedeutet zu sehr sehr unterschiedlichen Dingen

Leider verwendet die Terminologie dieselben Wörter, aber Sie können versuchen, "Schrittkomplexität" in Ihrem Kopf zu verwenden und sich Ihre Frage erneut zu stellen. Ich hoffe, das hilft Ihnen zu verstehen, dass die Antwort wirklich ^ _ ^ lautet


1 Dies erklärt auch die Notwendigkeit eines asymptotischen Ansatzes, da jede Instanz eine andere, jedoch nicht willkürliche Länge hat.
2 Ich hoffe, ich verwende hier den richtigen englischen Begriff.
3 Auch deshalb finden wir häufig log(log(n))Begriffe in der Mathematik.
4 Im besten Fall muss ein Schritt ein endliches, aber nicht nulles oder nicht verbundenes Zeitintervall einnehmen.
5 Dies bedeutet, dass der Rechenmodus als Kenntnis der physikalischen Zeit darin, dh mit seinen Begriffen ausgedrückt werden kann. Eine Analogie ist die Funktionsweise von Generika im .NET Framework.

Yuni Mj
quelle
3
"Ihre große O-Laufzeit ist also nur". Ich bin sicher, Sie meinten "große O-Komplexität"?. Außerdem können wir 'deltaTime' immer noch als unser 'n' Recht bezeichnen. Ihr Sprichwort O (2 ^ N) entspricht also der Komplexität des Fibonacci-Algorithmus. Wie bist du zur "2 ^" gekommen?
Ross
@ Ross, danke für den Punkt. Ich kam mit 2 aus Gewohnheit für die Arbeit mit Binärzahlen. Der Punkt ist, dass die Schritte linear mit der Länge der Darstellung der Zahl sind. Die tatsächliche Basis ist nicht wirklich wichtig und hängt von der spezifischen Codierung ab. Es ist pseudolinear .
Yuni Mj
Es tut mir leid, aber könnten Sie bitte in Ihrer Antwort näher erläutern, wie Sie zu dem Schluss gekommen sind, dass die Komplexität ist O(2^n)? Für Anfänger ist das nicht klar.
Arturo Torres Sánchez
2
@YuniMj Obwohl Ihre Argumentation technisch nicht falsch ist, denke ich, dass Sie nur zusätzliche Verwirrung stiften, wenn Sie darauf bestehen, die Größe von DeltaTimeanstelle des Werts zu messen . Zum Beispiel, aber diese Argumentation, kein optimaler Sortieralgorithmus hat Zeitkomplexität $ O (n \ cdot log n) $. Warum? Da Sie entweder nur endlich viele unterscheidbare Objekte sortieren müssen, können Sie in diesem Fall immer die Bucket-Sortierung verwenden, um $ O (n) $ zu sortieren. Oder Ihre Objektgröße ist unbegrenzt. In diesem Fall gilt $ O (n \ cdot log n) $ nicht, da ein einzelner Vergleich keine konstante Zeit mehr hat ...
fgp
1
FWIW O (2 ^ n)! = O (10 ^ n) stackoverflow.com/questions/19081673/…
Nathan FD
29

Obwohl es hier eine Reihe großartiger Antworten gibt, möchte ich sie alle ein wenig umformulieren.

Es gibt eine Big-O-Notation zur Beschreibung von Funktionen . Bei der Analyse von Algorithmen müssen wir zunächst einige Merkmale dieses Algorithmus in Bezug auf eine Funktion definieren . Die übliche Wahl besteht darin, die Anzahl der Schritte als Funktion der Eingabegröße zu berücksichtigen . Wie in anderen Antworten erwähnt, erscheint es seltsam, in Ihrem Fall eine solche Funktion zu entwickeln, da es keine klar definierte "Eingabe" gibt. Wir können es trotzdem versuchen:

  • Wir können Ihren Algorithmus als eine konstante Funktion betrachten, die jede Eingabe jeder Größe akzeptiert, ignoriert, eine festgelegte Zeitspanne wartet und beendet wird. In diesem Fall ist seine Laufzeit f (n) = const und es ist ein O (1) -Zeitalgorithmus. Das haben Sie erwartet, richtig? Ja, es ist technisch gesehen ein O (1) -Algorithmus .
  • Wir können den TwentyYearsLaterals "Eingabegröße" -ähnlichen Parameter von Interesse betrachten. In diesem Fall ist die Laufzeit f (n) = (nx), wobei x die "Jetzt-Zeit" zum Zeitpunkt des Aufrufs ist. So gesehen handelt es sich um einen O (n) -Zeitalgorithmus. Erwarten Sie dieses Gegenargument, wenn Sie anderen Ihren technischen O (1) -Algorithmus zeigen .
  • Oh, aber warte, wenn k =TwentyYearsLater die Eingabe ist, dann ist seine Größe n tatsächlich die Anzahl der Bits, die benötigt werden, um sie darzustellen, dh n = log (k) . Die Abhängigkeit zwischen der Größe der Eingabe n und der Laufzeit beträgt daher f (n) = 2 ^ n - x . Ihr Algorithmus scheint gerade exponentiell langsam geworden zu sein! Pfui.
  • Eine weitere Eingabe in das Programm ist in der Tat der Strom von Antworten, die das Betriebssystem auf die Reihenfolge der DateTime.NowAufrufe in der Schleife gibt. Wir können uns tatsächlich vorstellen, dass diese gesamte Sequenz zum Zeitpunkt der Ausführung des Programms als Eingabe bereitgestellt wird. Es kann dann davon ausgegangen werden, dass die Laufzeit von der Eigenschaft dieser Sequenz abhängt - nämlich von ihrer Länge bis zum ersten TwentyYearsLaterElement. In diesem Fall ist die Laufzeit wieder f (n) = n und der Algorithmus ist O (n) .

Andererseits haben Sie in Ihrer Frage nicht einmal gesagt, dass Sie an Laufzeit interessiert sind. Was wäre, wenn Sie die Speichernutzung meinen würden? Abhängig davon, wie Sie die Situation modellieren, können Sie sagen, dass der Algorithmus O (1) -Speicher oder möglicherweise O (n) -Speicher ist (wenn die Implementierung von DateTime.Nowerfordert, dass die gesamte Aufrufsequenz irgendwo verfolgt wird).

Und wenn Ihr Ziel darin bestand, etwas Absurdes zu finden, warum gehen Sie nicht all-in und sagen, dass Sie daran interessiert sind, wie die Größe des Algorithmuscodes in Pixel auf dem Bildschirm von der gewählten Zoomstufe abhängt. Dies könnte so etwas wie f (Zoom) = 1 / Zoom sein und Sie können stolz Ihren Algorithmus als O (1 / n) Pixel groß deklarieren!

KT.
quelle
+1. Ich glaube, der "Strom von Antworten, die das Betriebssystem auf die Reihenfolge der DateTime.NowAufrufe gibt", ist hier die eigentliche Eingabe. Aber ich denke, die Schlussfolgerung sollte nicht sein, dass es O (n) ist, sondern O (k), wobei k die Länge ist bis zum ersten TwentyYearsLaterElement.
halb
7
Dies ist die bisher beste Antwort - damit Big O aussagekräftig ist, müssen Sie mathematische Semantik / Annahmen auf die physikalische Implementierung anwenden (im Wesentlichen ein mathematisches Modell für das Programm mit einer aussagekräftigen Definition von "Eingabe" definieren). In diesem Sinne hängt die Komplexität des "Programms" von der Semantik ab, die Sie anwenden. Wenn Sie annehmen, dass N die Zeitdifferenz ist, die linear mit der Anzahl der Operationen skaliert, ist es O (n). Wenn Sie aufgrund eines festgelegten Zeitraums eine feste Anzahl von Operationen annehmen, ist dies O (1).
Ant P
21

Ich muss Servy etwas widersprechen. Es gibt eine Eingabe für dieses Programm, auch wenn es nicht offensichtlich ist, und das ist die Zeit des Systems. Dies könnte eine Technik sein, die Sie nicht beabsichtigt hatten, aber Ihre TwentyYearsFromNowVariable ist nicht zwanzig Jahre von der Zeit des Systems entfernt , sondern statisch dem 1. Januar 2035 zugeordnet.

Wenn Sie diesen Code auf einem Computer mit einer Systemzeit vom 1. Januar 1970 ausführen, dauert die Fertigstellung 65 Jahre, unabhängig davon, wie schnell der Computer ist (bei fehlerhafter Uhr kann es zu Abweichungen kommen ). Wenn Sie diesen Code auf einem Computer mit einer Systemzeit vom 2. Januar 2035 ausführen, wird er fast sofort abgeschlossen.

Ich würde sagen, Ihre Eingabe nistJanuary 1st, 2035 - DateTime.Now und es ist O (n).

Dann gibt es noch das Problem der Anzahl der Operationen. Einige Leute haben bemerkt, dass schnellere Computer schneller in die Schleife kommen und mehr Operationen verursachen, aber das ist irrelevant. Bei der Arbeit mit Big-O-Notation berücksichtigen wir weder die Geschwindigkeit des Prozessors noch die genaue Anzahl der Vorgänge. Wenn Sie diesen Algorithmus verwenden und ihn auf einem Computer ausführen und dann erneut ausführen, jedoch 10x länger auf demselben Computer, würden Sie erwarten, dass die Anzahl der Vorgänge um den gleichen Faktor von 10x zunimmt.

Was das betrifft:

Ich denke darüber nach, das Codeausschnitt [redigierter Code] als Besetztschleife zu verwenden, um es als Witz einzufügen, wenn jemand nach einem Algorithmus einer bestimmten Komplexität fragt. Wäre das richtig?

Nein nicht wirklich. Andere Antworten haben dies behandelt, deshalb wollte ich es nur erwähnen. Sie können jahrelange Ausführung im Allgemeinen nicht mit einer Big-O-Notation korrelieren. Z.B. Es gibt keine Möglichkeit, 20 Jahre Hinrichtung = O (n ^ 87) oder irgendetwas anderes zu sagen. Selbst in dem von Ihnen angegebenen Algorithmus könnte ich das TwentyYearsFromNowauf das Jahr 20110, 75699436 oder 123456789 ändern, und das große O ist immer noch O (n).

Shaz
quelle
7
Die Zeit ist keine Eingabe für die Funktion, sondern ändert ständig den Zustand , der während der Ausführung der Methode beobachtet wird. Die Systemuhr kann sogar bei laufender Funktion geändert werden . Damit Big O aussagekräftig ist, muss jeder Eingang 1-1 mit einem Ausgabewert sowie einer Reihe von Operationen übereinstimmen, die zur Berechnung erforderlich sind. Für diese Operation auch nicht konsistent für den gleichen Eingang des Ausgangs (tatsächlich variiert wild ), zusätzlich zu der Anzahl von Operationen durchgeführt , auch sehr unterschiedlich.
Servy
When working with big-O notation, we don't consider the speed of the processor or the exact number of operations.Dies ist eine falsche Aussage. So ziemlich jeder vernünftiger Betrieb , dass Sie versuchen würden , den Big O Wert zu berechnen , wird nicht die Anzahl der Operationen ändern durchgeführt , basierend auf der Hardware, aber dies tut . Big O ist nur eine Möglichkeit, die Anzahl der Operationen mit der Größe der Eingabe in Beziehung zu setzen. Für die meisten Vorgänge unabhängig von der Systemhardware. In diesem Fall ist es nicht .
Servy
If you took this algorithm and ran it on a computer, and then ran it again but for 10x longer on the same computer, you would expect the number of operations to grow by the same factor of 10x.Das ist auch eine falsche Aussage. Die Umgebung ändert die Anzahl der Operationen in der Schleife nicht unbedingt linear. Es könnten beispielsweise andere Programme auf dem Computer vorhanden sein, die zu unterschiedlichen Zeitpunkten mehr oder weniger CPU-Zeit verbrauchen und die dieser Anwendung im Laufe der Zeit ständig zugewiesene Zeit ändern.
Servy
Ich bin mit @Servy in diesem Fall, aber aus einem etwas anderen Grund. Die Hauptfunktion akzeptiert keine Parameter und gibt keine Eingabe zurück. Es ist eine Funktion von nil => nil, wenn Sie möchten. Egal wie spät es ist, es gibt immer noch nichts zurück.
Steve Cooper
1
Wenn wir diese Definition verwenden - "In der Mathematik ist eine Funktion eine Beziehung zwischen einer Reihe von Eingaben und einer Reihe zulässiger Ausgaben mit der Eigenschaft, dass jede Eingabe mit genau einer Ausgabe verknüpft ist." (wikipedia) - und wir zählen die Konsolenausgabe als 'Ausgabe der Funktion', dies variiert und wird auf schnelleren Computern länger, da geschrieben wird "" Es ist immer noch nicht Zeit, das Hallo zu drucken ... "" öfters.
Steve Cooper
13

Die Big-O-Analyse befasst sich mit dem Verarbeitungsaufwand, da die verarbeitete Datenmenge unbegrenzt zunimmt.

Hier handelt es sich wirklich nur um ein einzelnes Objekt fester Größe. Daher hängt die Anwendung der Big-O-Analyse stark (hauptsächlich?) Davon ab, wie Sie Ihre Begriffe definieren.

Zum Beispiel könnten Sie bedeuten, die Ausgabe im Allgemeinen zu drucken und so lange zu warten, bis eine angemessene Datenmenge in genau demselben Zeitraum gedruckt wird / wird. Sie müssen auch etwas mehr ungewöhnliche (wenn nicht völlig falsche) Definitionen hinzufügen, um sehr weit zu kommen - insbesondere bei Big-O-Analysen ist dies normalerweise der Fall anhand der Anzahl der grundlegenden Operationen definiert, die zur Durchführung von a erforderlich sind bestimmte Aufgabe (beachten Sie jedoch, dass Komplexität auch in Bezug auf die Speichernutzung und nicht nur die CPU-Auslastung / ausgeführte Operationen berücksichtigt werden kann).

Die Anzahl der grundlegenden Operationen entspricht jedoch in der Regel ziemlich genau der Zeit, die benötigt wird. Daher ist es keine große Herausforderung, die beiden als synonym zu behandeln. Leider bleiben wir jedoch bei diesem anderen Teil: Die Menge der verarbeiteten Daten nimmt unbegrenzt zu. In diesem Fall funktioniert keine feste Verzögerung, die Sie auferlegen können, wirklich. Um O (1) mit O (N) gleichzusetzen, müssten Sie eine unendliche Verzögerung festlegen, damit das Drucken einer festen Datenmenge ewig dauerte, genau wie eine unendliche Datenmenge.

Jerry Sarg
quelle
10

Big-O relativ zu was?

Sie scheinen zu verstehen, dass dies twentyYearsLatereine "Eingabe" ist. Wenn Sie tatsächlich Ihre Funktion als geschrieben haben

void helloWorld(int years) {
   // ...
}

Es wäre O (N), wo N = Jahre (oder einfach sagen) O(years) ).

Ich würde sagen, Ihr Algorithmus ist O (N) relativ zu der Zahl, mit der Sie in die Codezeile schreiben, beginnend mit twentyYearsLater = . Normalerweise betrachten die Leute Zahlen im eigentlichen Quellcode jedoch nicht als Eingabe. Sie betrachten möglicherweise die Befehlszeileneingabe als Eingabe oder die Funktionssignatureingabe als Eingabe, höchstwahrscheinlich jedoch nicht den Quellcode selbst. Das ist es, was Sie mit Ihrem Freund bestreiten - ist dies der "Input"? Sie richten Ihren Code so ein, dass er intuitiv wie eine Eingabe erscheint, und Sie können definitiv die große O-Laufzeit in Bezug auf die Nummer N in Zeile 6 Ihres Programms erfragen, aber wenn Sie eine solche nicht standardmäßige Auswahl verwenden Als Eingabe müssen Sie wirklich explizit darüber sein.

Wenn Sie jedoch die Eingabe als etwas Üblicheres betrachten, wie die Befehlszeile oder die Eingabe für die Funktion, gibt es überhaupt keine Ausgabe und die Funktion ist O (1). Es dauert zwanzig Jahre, aber da sich big-O nicht bis zu einem konstanten Vielfachen ändert, ist O (1) = O (zwanzig Jahre).

Ähnliche Frage - was ist die Laufzeit von:

void sortArrayOfSizeTenMillion(int[] array)

Angenommen, es tut, was es sagt, und die Eingabe ist gültig, und der Algorithmus nutzt eine Quicksort- oder Blasensortierung oder irgendetwas Vernünftiges, dann ist es O (1).

Djechlin
quelle
Das Hardcodieren der Eingabe bedeutet nicht, dass die Eingabe verschwindet. Auch Quicksort und Bubblesort sind in keinem Fall von O (1) -Zeitkomplexität. bigocheatsheet.com
Theo Brinkman
@TheoBrinkman Wenn Sie in einem Turing-Maschinenmodell technisch sein möchten und Ihre Meinung zur Eingabe in die Turing-Maschine selbst kodieren, wird diese per Definition nicht zur Eingabe. Die Turing-Maschine läuft dann in einer konstanten Zeit, unabhängig von der tatsächlichen Eingabe. In gewisser Weise wird keine "Blasensortierung" ausgeführt, da nichts sortiert wird, sondern eine eigene Darstellung verwendet wird. In nicht-technischen Begriffen könnte man den Algorithmus natürlich als Blasensortierung bezeichnen.
Djechlin
Ebenso "nicht technisch" könnte man den fraglichen Algorithmus als Hängebrücke beschreiben.
Theo Brinkman
@ TheoBrinkman nein, du konntest nicht. Das würde für niemanden Sinn machen.
Djechlin
Es ist genauso sinnvoll, es als O (1) -Blasensorte zu beschreiben.
Theo Brinkman
8

Dieser "Algorithmus" wird korrekt als O (1) oder konstante Zeit beschrieben. Es wurde argumentiert, dass es keinen Input für dieses Programm gibt, daher gibt es kein N, das in Bezug auf Big Oh analysiert werden muss. Ich bin nicht der Meinung, dass es keine Eingabe gibt. Wenn dies in eine ausführbare Datei kompiliert und aufgerufen wird, kann der Benutzer jede Eingabe beliebiger Länge angeben. Diese Eingangslänge ist die N.

Das Programm ignoriert nur die Eingabe (unabhängig von der Länge), sodass die benötigte Zeit (oder die Anzahl der ausgeführten Maschinenbefehle) unabhängig von der Länge der Eingabe (bei fester Umgebung = Startzeit + Hardware) gleich ist, daher O (1) ).

waldol1
quelle
Die Anzahl der Vorgänge ist jedoch nicht unbedingt konsistent, selbst bei gleicher Startzeit und Hardware. Hinzu kommt, dass eine O (1) Anspruch Algorithmus würde der Ausgang immer konstant sein muß, und es ist nicht, wird es variiert wild auf der Startzeit und Hardware basiert. Es könnte auch sehr leicht unendlich sein, was sicherlich nicht konstant ist. Es gibt keine Beziehung zwischen der von Ihnen definierten Eingabe und der Anzahl der ausgeführten Operationen. Das ist nicht konstant, das ist nur undefiniert. Sie können keine endliche Zahl nennen und wissen, dass es immer weniger Operationen als diese geben wird.
Servy
Die maximale Echtzeit beträgt 20 Jahre. Wenn wir es in Zukunft starten, wird es ja länger dauern. Nehmen wir an, dass es eine endliche Untergrenze für die Zeit gibt, die eine Schleifeniteration benötigt, und dass wir auf serieller Hardware arbeiten. Dann kann ich festlegen, wie oft die Schleife ausgeführt wird, was bedeutet, dass die gesamte Berechnung durch eine konstante Funktion begrenzt werden kann, unabhängig von der Größe der ignorierten Eingabe.
Waldol1
Let's suppose that there is a finite lower bound on the amount of time a loop iteration takesDas ist eine falsche Annahme. Das Programm kann für immer laufen. Alles, was ich tun muss, ist, meine Systemuhr auf 50 Jahre einzustellen, sie zu starten und sie wird niemals beendet. Oder ich könnte die Uhr schneller zurückbewegen als vorwärts oder an einem unbestimmten Punkt in der Vergangenheit starten . Sie können einfach nicht davon ausgehen, dass es eine Untergrenze für die Laufzeit des Programms gibt. es kann für immer laufen. Aber selbst wenn wir Ihre (falsche) Annahme als wahr annehmen, können Sie die Anzahl der ausgeführten Operationen nicht mit der Eingabe in Beziehung setzen.
Servy
Eine Einzelschleifeniteration benötigt eine begrenzte Zeit. Es kann möglich sein, dass es unendlich oft ausgeführt wird, aber jedes sollte ungefähr konstant sein. Ich sehe kein Problem mit dieser Annahme.
Waldol1
Durch diese [völlig falsche] Logik ist jeder einzelne Algorithmus immer O (1), weil jede einzelne Operation immer konstant ist. Sie demonstrieren lediglich, dass Sie nicht wissen, was Big O überhaupt ist. Es ist ein Werkzeug zur (im Kontext) Beschreibung der Beziehung zwischen der Größe der Eingabe und der Anzahl der durchgeführten relevanten Operationen. O (1) bedeutet, dass unabhängig von der Eingabe eine konstante Anzahl von Operationen ausgeführt wird. Hier wird unabhängig von der Eingabe keine konstante Anzahl von Operationen ausgeführt, es werden möglicherweise unendlich viele Operationen ausgeführt, unendlich! = Konstante.
Servy
6

Eine Sache, die mich überrascht, wurde noch nicht erwähnt: Die Big-O-Notation ist eine Obergrenze!

Das Problem, das jeder bemerkt hat, ist, dass es kein N gibt, das die Eingaben in den Algorithmus beschreibt, so dass es nichts gibt, mit dem man eine Big-O-Analyse durchführen kann. Dies lässt sich jedoch leicht durch einige grundlegende Tricks abmildern, z. B. das Akzeptieren int nund Drucken von "Hello World" n-Zeiten. Das würde diese Beschwerde umgehen und auf die eigentliche Frage zurückkommen, wie diese DateTimeMonstrosität funktioniert.

Es gibt keine tatsächliche Garantie dafür, dass die while-Schleife jemals beendet wird. Wir denken gerne, dass es irgendwann sein muss, aber denken Sie daran , dass DateTime.nowdas System Datum und Uhrzeit zurückgibt . Es gibt eigentlich keine Garantie dafür, dass dies monoton zunimmt. Es ist möglich, dass ein pathologisch ausgebildeter Affe das Datum und die Uhrzeit des Systems ständig auf den 21. Oktober 2015 um 12:00:00 UTC ändert, bis jemand dem Affen einige automatisch passende Schuhe und ein Hoverboard gibt. Diese Schleife kann tatsächlich unendlich lange laufen!

Wenn Sie sich tatsächlich mit der mathematischen Definition von Big-O-Notationen befassen, handelt es sich um Obergrenzen. Sie zeigen das Worst-Case-Szenario, egal wie unwahrscheinlich. Das Worst-Case * -Szenario hier ist eine unendliche Laufzeit, daher müssen wir deklarieren, dass es keine Big-O-Notation gibt, um die Laufzeitkomplexität dieses Algorithmus zu beschreiben. Es existiert nicht, genauso wie 1/0 nicht existiert.

* Bearbeiten: Aus meiner Diskussion mit KT geht nicht immer hervor, dass das Szenario, das wir mit Big-O-Notation modellieren, der schlimmste Fall ist. In den meisten Fällen wollte eine Person, wenn sie nicht angibt, welchen Fall wir verwenden, den schlimmsten Fall untersuchen. Sie können jedoch eine Big-O-Komplexitätsanalyse zur besten Laufzeit durchführen.

Cort Ammon
quelle
2
O ist in gewissem Sinne zwar eine "Obergrenze", aber das bedeutet nicht, dass Sie nur mit der O-Notation von "Worst-Case-Komplexität" sprechen können. Erwartete Komplexität, Best-Case-Komplexität, jede andere funktionale Eigenschaft - alle können im Hinblick auf ihre O-Grenzen diskutiert werden.
KT.
@KY Best-Case-Komplexität wird als Little-O bezeichnet, und die erwartete Komplexität ist Big-Theta. big-o ist nach seiner mathematischen Definition immer die Worst-Case-Komplexität.
Cort Ammon
Nein, Sie irren sich hier. Überprüfen Sie die Definitionen erneut.
KT.
@KT Okay, ich werde sie noch einmal überprüfen. Sie überprüfen sie auch erneut. en.wikipedia.org/wiki/Big_O_notation Es ist unter Familie der Bachmann-Landau-Notationen
Cort Ammon
Ich nehme an, Sie könnten etwas Wahnsinniges tun, wie eine Funktion zu übernehmen fund die Funktion gals dieselbe zu deklarieren f, aber mit einer eingeschränkten Domain, die nur den fbesten Fall enthält, und dann Big-Oh-On ausführen g, aber es beginnt zu degenerieren, wenn Sie dies tun Das.
Cort Ammon
5

Die Komplexität wird verwendet, um die rechnerische "Leistung" in Bezug auf Zeit / Raum zu messen. Die Big O-Notation wird verwendet, um zu vergleichen, welche Probleme "berechenbar" oder "nicht berechenbar" sind, und um zu vergleichen, welche Lösungen - Algorithmen - besser sind als andere. Daher können Sie jeden Algorithmus in zwei Kategorien einteilen: diejenigen, die in Polynomzeit gelöst werden können, und diejenigen, die dies nicht können.

Probleme wie das Sieb von Erathostene sind O (n ^ exp) und daher für kleine Werte von n lösbar. Sie sind berechenbar, nur nicht in der Polynomzeit (NP). Wenn Sie also gefragt werden, ob eine bestimmte Zahl eine Primzahl ist oder nicht, hängt die Antwort von der Größe dieser Zahl ab. Darüber hinaus hängt die Komplexität nicht von der Hardware ab, sodass schnellere Computer nichts ändern ...

Hello World ist kein Algorithmus und daher sinnlos zu versuchen, seine Komplexität zu bestimmen - was keiner ist. Ein einfacher Algorithmus kann ungefähr so ​​aussehen: Bestimmen Sie anhand einer Zufallszahl, ob er gerade oder ungerade ist. Ist es nun wichtig, dass die angegebene Nummer 500 Stellen hat? Nein, weil Sie nur prüfen müssen, ob die letzte Ziffer gerade oder ungerade ist. Ein komplexerer Algorithmus wäre zu bestimmen, ob eine bestimmte Zahl gleichmäßig durch 3 geteilt wird. Obwohl einige Zahlen "einfach" zu berechnen sind, sind andere "schwer" und dies liegt an ihrer Größe: Vergleichen Sie die Zeit, die zur Bestimmung der Remaninder zwischen benötigt wird eine Zahl mit einer Ziffer und eine andere mit 500 Ziffern.

Ein komplexerer Fall wäre das Dekodieren eines Textes. Sie haben eine scheinbar zufällige Anordnung von Symbolen, von denen Sie auch wissen, dass sie eine Nachricht für diejenigen übermitteln, die den Entschlüsselungsschlüssel haben. Angenommen, der Absender hat den Schlüssel links verwendet und Ihre Hello World würde lauten: Gwkki Qieks. Die "Big-Hammer, No-Brain" -Lösung würde alle Kombinationen für diese Buchstaben erzeugen: von Aaaa bis Zzzz und dann ein Wortwörterbuch durchsuchen, um zu identifizieren, welche Wörter gültig sind, und die beiden gemeinsamen Buchstaben in der Chiffre (i, k) in teilen die gleiche Position. Diese Transformationsfunktion misst Big O!

Turing
quelle
4

Den meisten Menschen scheinen zwei sehr wichtige Dinge zu fehlen.

  1. Das Programm hat einen Eingang. Dies ist das fest codierte Datum / die fest codierte Uhrzeit, mit der die Systemzeit verglichen wird. Die Eingaben werden von der Person gesteuert, die den Algorithmus ausführt, die Systemzeit jedoch nicht. Die Person, die dieses Programm ausführt, kann nur das Datum und die Uhrzeit steuern, die sie im Vergleich fest codiert hat.

  2. Das Programm hängt von der Grundlage des eingegebenen Wert , aber nicht die Größe des Eingangssatzes , das ist das, was Big-O - Notation mit betroffen ist .

Daher ist es unbestimmt, und die beste 'Big-O'-Notation für dieses Programm wäre wahrscheinlich O (null) oder möglicherweise O (NaN).

Theo Brinkman
quelle
1
(2) ist absolut falsch. Normalerweise wird die "Länge der Eingabe" berücksichtigt. Für eine Liste oder ein Array von Objekten fester Größe (wie Ganzzahlen) entspricht dies in der Tat der Größe der Menge. Um eine Zahl wie 1395195191600333 zu faktorisieren, ist dies die Länge ihrer binären (oder dezimalen usw.) Darstellung, dh die Anzahl der Ziffern. Wie bereits erwähnt, verbietet Ihre Definition in (2) die Verwendung von Big-O, um die Komplexität von "findPrimeFactors (int num)" zu diskutieren, gegen die fast jeder Kryptograf Einwände erheben wird.
Djechlin
4

Jeder hat richtig darauf hingewiesen, dass Sie nicht N definieren , aber die Antwort ist nein unter der vernünftigsten Interpretation. Wenn N die Länge der Zeichenfolge ist, die wir drucken, und "Hallo, Welt!" ist nur ein Beispiel, wie wir aus der Beschreibung dieses Algorithmus als "für hello, world!" schließen könnten , dann ist der Algorithmus O ( N ), weil Sie möglicherweise eine Ausgabezeichenfolge haben, deren Druck dreißig, vierzig oder fünfzig Jahre dauert, und Sie füge dem nur eine konstante Zeit hinzu. O ( kN + c ) ≤ O ( N ).

Nachtrag:

Zu meiner Überraschung bestreitet dies jemand. Erinnern Sie sich an die Definitionen von big O und big Θ. Angenommen, wir haben einen Algorithmus, der auf eine konstante Zeit c wartet und dann eine Nachricht der Länge N in linearer Zeit druckt . (Dies ist eine Verallgemeinerung des ursprünglichen Codebeispiels.) Nehmen wir willkürlich an, wir warten zwanzig Jahre, um mit dem Drucken zu beginnen, und das Drucken von Billionen Zeichen dauert weitere zwanzig Jahre. Es sei zum Beispiel c = 20 und k = 10¹², aber alle positiven reellen Zahlen reichen aus. Das ist eine Rate von d = c / k (in diesem Fall 2 × 10¹¹) Jahren pro Zeichen, also unsere Ausführungszeit f ( N ) asymptotisch cdN + Jahre. Immer wenn N > k , ist dN = c / k N > c . Daher ist dN < dN + c = f ( N ) <2 dN für alle N > k und f ( N ) ∈ ∈ ( N ). QED

Davislor
quelle
Wo wir N = 13 haben.
Djechlin
Es wird jedoch nicht nur "Hallo Welt" gedruckt, sondern auch eine unbekannte Anzahl von "Es ist immer noch keine Zeit" -Zeilen. Außerdem wird Big O nicht wirklich verwendet, um die Größe der Eingabe mit der Größe der Ausgabe zu vergleichen. Es wird im Allgemeinen verwendet, um die Größe der Eingabe mit der Anzahl der Operationen oder der verwendeten Speichermenge zu vergleichen.
Servy
@Servy Es ist ein konstanter Speicher, aber ich habe die Ausführungszeit implizit begrenzt. Die Größe der Ausgabe ist für eine beliebige Zeichenfolge ebenfalls O ( N ): Die Zeichenfolge, die wir drucken, wenn es Zeit ist, kann beliebig groß sein, selbst im Vergleich zu Nachrichten mit einer Wartezeit von zwanzig Jahren.
Davislor
@Servy Ich habe bearbeitet, um zu verdeutlichen, dass N hier nicht die Größe der Ausgabe ist. Ich bin mir nicht sicher, wie ich diesen Eindruck erweckt habe, aber ich werde jede Unklarheit beseitigen.
Davislor
1
Wenn Sie also davon ausgehen, dass das Programm eine Eingabe nimmt, wenn dies nicht der Fall ist, kann die Ausgabe beliebig groß sein, wenn dies nicht möglich ist, dass die Schleife nichts tut, wenn dies der Fall ist und dass die Ausgabe in Beziehung steht die Eingabe, wenn es nicht ist, dann ja, das Programm ist linear. Natürlich ist jede einzelne dieser Annahmen völlig falsch, daher gilt die Schlussfolgerung, die Sie daraus gezogen haben, nicht. Wenn Sie in der Lage sind, Ihren Standpunkt zu demonstrieren, ohne falsche Annahmen zu treffen, dann würde dies etwas bedeuten.
Servy
4

Ich denke, die Leute werden abgeworfen, weil der Code nicht wie ein traditioneller Algorithmus aussieht . Hier ist eine Übersetzung des Codes, die wohlgeformter ist, aber dem Geist der OP-Frage treu bleibt.

void TrolloWorld(long currentUnixTime, long loopsPerMs){
    long laterUnixTime = 2051222400000;  //unix time of 01/01/2035, 00:00:00
    long numLoops = (laterUnixTime-currentUnixTime)*loopsPerMs;

    for (long i=0; i<numLoops; i++){
        print ("It's still not time to print the hello …");
    }
    print("Hello, World!");
}

Die Eingaben sind explizit, während sie zuvor implizit zum Zeitpunkt des Starts des Codes und zur Geschwindigkeit der Hardware, auf der der Code ausgeführt wird, angegeben wurden. Der Code ist deterministisch und hat eine genau definierte Ausgabe für bestimmte Eingaben.

Aufgrund der Einschränkungen, die den von uns bereitgestellten Eingaben auferlegt werden, gibt es eine Obergrenze für die Anzahl der Operationen, die ausgeführt werden, sodass dieser Algorithmus tatsächlich O (1) ist.

Nathan FD
quelle
2

Zu diesem Zeitpunkt ja

Dieser Algorithmus hat eine implizite Eingabe, nämlich die Zeit, zu der das Programm gestartet wird. Die Ausführungszeit variiert linear 1, je nachdem, wann sie gestartet wird. Während des Jahres 2035 und danach wird die while-Schleife sofort beendet und das Programm endet nach konstanten Operationen 2 . Man könnte also sagen, dass die Laufzeit O(max(2035 - start year, 1))3 ist . Da unser Startjahr jedoch einen Mindestwert hat, wird die Ausführung des Algorithmus nie länger als 20 Jahre dauern (dh einen konstanten Wert).

Sie können Ihren Algorithmus besser an Ihre Absicht anpassen, indem Sie 4 definierenDateTime TwentyYearsLater = DateTime.Now + new TimeSpan(365*20,0,0,0);

1 Dies gilt für das technischere Gefühl der Ausführungszeit, gemessen als Anzahl der Operationen, da es eine maximale Anzahl von Operationen pro Zeiteinheit gibt.
2 Angenommen, das Abrufen DateTime.Nowist eine konstante Operation, die sinnvoll ist.
3 Ich missbrauche hier die große O-Notation etwas, weil dies eine abnehmende Funktion in Bezug auf ist start year, aber wir könnten dies leicht korrigieren, indem wir sie in Bezug auf ausdrücken years prior to 2035.
4 Dann hängt der Algorithmus nicht mehr von der impliziten Eingabe der Startzeit ab, aber das hat keine Konsequenz.

Nathan FD
quelle
1

Ich würde argumentieren, dass dies O (n) ist. Verwenden von http://www.cforcoding.com/2009/07/plain-english-explanation-of-big-o.html als Referenz.

Was ist Big O?

Die Big O-Notation versucht, die relative Komplexität eines Algorithmus zu beschreiben, indem die Wachstumsrate auf die Schlüsselfaktoren reduziert wird, wenn der Schlüsselfaktor gegen unendlich tendiert.

und

Das beste Beispiel für Big-O, das ich mir vorstellen kann, ist das Rechnen. Die grundlegenden arithmetischen Operationen, die wir in der Schule gelernt haben, waren:

Zusatz; Subtraktion; Multiplikation; und Teilung. Jedes davon ist eine Operation oder ein Problem. Eine Methode zur Lösung dieser Probleme wird als Algorithmus bezeichnet.

Für Ihr Beispiel

gegeben die Eingabe von n = 20 (mit Einheiten Jahre).

Der Algorithmus ist eine mathematische Funktion f (). Dabei wartet f () n Jahre lang mit dazwischen liegenden 'Debug'-Zeichenfolgen. Der Skalierungsfaktor ist 1. f () kann durch Ändern dieses Skalierungsfaktors verringert / oder erhöht werden.

In diesem Fall beträgt der Ausgang ebenfalls 20 (durch Ändern des Eingangs wird der Ausgang linear geändert).

im wesentlichen ist die Funktion

f(n) = n*1 = n
    if  n = 20, then 
f(20) = 20 
Engel Koh
quelle