filter
hat n
rekursive Aufrufe, aber Sie tun auch eine Kopieroperation bei jeder Iteration, die n
dauert, so dass Sie am Ende Θ (n^2) haben. Wenn Sie es "richtig" implementiert haben, sollte es Θ (n) sein.
Dasselbe gilt für my_reverse
.
Dasselbe gilt für revfilter_beta
.
revfilter_alpha
macht genau eine filter
und dann ein reverse
, damit ist, Θ (n^2 + n^2) = Θ (n^2).
EDIT: Lassen Sie uns einen Blick in filter
ein bisschen mehr.
Was Sie herausfinden möchten, ist, wie viele Operationen relativ zur Größe der Eingabe durchgeführt werden. O(n)
bedeutet, dass im schlimmsten Fall in der Größenordnung von n
Operationen durchgeführt werden. Ich sage "in der Größenordnung von", weil Sie zum Beispiel O(n/2)
Operationen oder O(4n)
tun können, aber der wichtigste Faktor ist n
. Das heißt, wenn n
wächst, wird der konstante Faktor immer weniger wichtig, so dass wir nur den nichtkonstanten Faktor betrachten (n
in diesem Fall).
Also, wie viele Operationen führt filter
auf einer Liste der Größe n
?
Nehmen wir es von unten nach oben. Was ist, wenn n
0 ist - eine leere Liste? Dann wird nur eine leere Liste zurückgegeben. Sagen wir mal, das ist 1 Operation.
Was ist, wenn n
1 ist? Es wird geprüft, ob lst[0]
enthalten sein sollte - diese Prüfung dauert so lange, bis f
aufgerufen wird - und dann wird der Rest der Liste kopiert und ein rekursiver Aufruf dieser Kopie ausgeführt, was in diesem Fall eine leere Liste ist. so filter(1)
dauert f + copy(0) + filter(0)
Operationen, wobei copy(n)
ist, wie lange es dauert, um eine Liste zu kopieren, und f
ist, wie lange es dauert zu prüfen, ob ein Element enthalten sein sollte, vorausgesetzt, es dauert die gleiche Zeit für jedes Element.
Was ist mit filter(2)
? Es wird 1 überprüfen, dann kopieren Sie den Rest der Liste und rufen Sie filter
auf den Rest: f + copy(1) + filter(1)
.
Sie können das Muster bereits sehen.filter(n)
dauert 1 + copy(n-1) + filter(n-1)
.
Jetzt copy(n)
ist nur n
- es dauert n
Operationen, die Liste auf diese Weise zu schneiden. So können wir weiter vereinfachen: filter(n) = f + n-1 + filter(n-1)
.
Jetzt können Sie versuchen, erweitern gerade filter(n-1)
ein paar Mal, um zu sehen, was passiert:
filter(n) = f + n-1 + filter(n-1)
= 1 + n-1 + (f + n-2 + filter(n-2))
= f + n-1 + f + n-2 + filter(n-2)
= 2f + 2n-3 + filter(n-2)
= 2f + 2n-3 + (f + n-3 + filter(n-3))
= 3f + 3n-6 + filter(n-3)
= 3f + 3n-6 + (f + n-4 + filter(n-4))
= 4f + 4n-10 + filter(n-4)
= 5f + 5n-15 + filter(n-5)
...
Können wir für x
Wiederholungen verallgemeinern? Die 1, 3, 6, 10, 15
... Sequenz ist die Dreieckszahlen - das heißt, 1
, 1+2
, 1+2+3
, 1+2+3+4
usw. Die Summe aller Zahlen 1
-x
ist x*(x-1)/2
.
= x*f + x*n - x*(x-1)/2 + filter(n-x)
Nun, was ist x
? Wie viele Wiederholungen werden wir haben? Nun, Sie können sehen, dass, wenn x
= n
, Sie keine Rekursion mehr haben - filter(n-n)
= filter(0)
= 1
. So ist unsere Formel ist jetzt:
filter(n) = n*f + n*n - n*(n-1)/2 + 1
Was wir weiter vereinfachen:
filter(n) = n*f + n^2 - (n^2 - n)/2 + 1
= n*f + n^2 - n^2/2 + n/2 + 1
= n^2 - n^2/2 + f*n + n/2 + 1
= (1/2)n^2 + (f + 1/2)n + 1
So gibt ya haben es - eine ziemlich detaillierte Analyse. Das wäre Θ((1/2)n^2 + (f + 1/2)n + 1)
... unter der Annahme, f
ist unbedeutend (etwa f
= 1), dass zu Θ((1/2)n^2 + (3/2)n + 1)
bekommt.
Sie werden nun feststellen, ob copy(n)
eine konstante Menge an Zeit statt eine Menge an Zeit linear nahmen (wenn copy(n)
1 statt n
sind), dann würden Sie da nicht, dass n^2
Begriff bekommen.
Ich gebe zu, wenn ich anfangs Θ(n^2)
gesagt habe, habe ich das nicht alles in meinem Kopf getan. Stattdessen dachte ich: ok, Sie haben n
rekursive Schritte, und jeder Schritt dauert n
Menge an Zeit wegen der copy
. n*n = n^2
, also Θ(n^2)
. Um das zu tun ein bisschen genauer, n
bei jedem Schritt schrumpft, so dass Sie wirklich n + (n-1) + (n-2) + (n-3) + ... + 1
haben, die endet als die gleiche Figur wie oben: n*n - (1 + 2 + 3 + ... + n)
= n*n - n*(n-1)/2
= (1/2)n^2 + (1/2)n
, die die gleiche ist, wenn ich 0
statt f
benutzt hatte, oben . Ebenso, wenn Sie n
Schritte hatten, aber jeder Schritt dauerte 1
anstelle von n
(wenn Sie die Liste nicht kopieren mussten), dann hätten Sie 1 + 1 + 1 + ... + 1
, n
mal, oder einfach n
.
Aber das erfordert ein bisschen mehr Intuition, also dachte ich, ich würde Ihnen auch die Brute-Force-Methode zeigen, die Sie auf alles anwenden können.
Wie viele rekursive Aufrufe werden in 'filter' gemacht? Ist es wirklich "n * n"? –
Vielleicht ist es tatsächlich Θ (n). – kayla
btw, da 'filter' genauso eingebaut ist wie' reverse' könnte man es auch 'my_filter' nennen. – Claudiu