Ich habe Schwierigkeiten zu entscheiden, wie zeitlich komplex Euklids größter gemeinsamer Nenner-Algorithmus ist. Dieser Algorithmus im Pseudocode lautet:
function gcd(a, b)
while b ≠ 0
t := b
b := a mod b
a := t
return a
Es scheint von a und b abzuhängen . Ich denke, dass die zeitliche Komplexität O ist (a% b). Ist das korrekt? Gibt es einen besseren Weg, das zu schreiben?
algorithm
big-o
time-complexity
iteration
Donald Taylor
quelle
quelle
a%b
. Der schlimmste Fall ist, wenna
undb
sind aufeinanderfolgende Fibonacci-Zahlen.Antworten:
Ein Trick zur Analyse der zeitlichen Komplexität des Euklid-Algorithmus besteht darin, zu verfolgen, was in zwei Iterationen geschieht:
Jetzt nehmen a und b statt nur eines ab, was die Analyse erleichtert. Sie können es in Fälle unterteilen:
2a <= b
2b <= a
2a > b
abera < b
2b > a
aberb < a
a == b
Jetzt zeigen wir, dass jeder einzelne Fall die Summe
a+b
um mindestens ein Viertel verringert :b % (a % b) < a
und2a <= b
, sob
wird um mindestens die Hälftea+b
verringert , so um mindestens verringert25%
a % b < b
und2b <= a
wird alsoa
um mindestens die Hälftea+b
verringert , also um mindestens die Hälfte verringert25%
b
wirdb-a
, was kleiner als istb/2
,a+b
mindestens um abnehmend25%
.a
wirda-b
, was kleiner als ista/2
,a+b
mindestens um abnehmend25%
.a+b
fällt auf0
, was offensichtlicha+b
um mindestens abnimmt25%
.Daher verringert sich
a+b
durch Fallanalyse jeder Doppelschritt um mindestens25%
. Es gibt eine maximale Anzahl von Malen, die passieren können, bevora+b
sie nach unten fallen müssen1
. Die Gesamtzahl der Schritte (S
), bis wir 0 erreichen, muss erfüllt sein(4/3)^S <= A+B
. Jetzt arbeite es einfach:Die Anzahl der Iterationen ist also linear in der Anzahl der Eingangsziffern. Für Zahlen, die in CPU-Register passen, ist es sinnvoll, die Iterationen so zu modellieren, dass sie eine konstante Zeit benötigen, und so zu tun, als ob die Gesamtlaufzeit der GCD linear wäre.
Wenn Sie mit großen Ganzzahlen arbeiten, müssen Sie natürlich berücksichtigen, dass die Moduloperationen innerhalb jeder Iteration keine konstanten Kosten verursachen. Grob gesagt wird die gesamte asymptotische Laufzeit das n ^ 2-fache eines polylogarithmischen Faktors betragen. So etwas wie
n^2 lg(n) 2^O(log* n)
. Der polylogarithmische Faktor kann vermieden werden, indem stattdessen ein binärer gcd verwendet wird .quelle
x % y
kann nicht mehr als seinx
und muss kleiner sein alsy
. Ista % b
also höchstensa
gezwungenb % (a%b)
, unter etwas zu sein, das höchstensa
und daher insgesamt kleiner ist alsa
.Die geeignete Methode zur Analyse eines Algorithmus besteht darin, seine Worst-Case-Szenarien zu ermitteln. Der schlimmste Fall der euklidischen GCD tritt auf, wenn Fibonacci-Paare beteiligt sind.
void EGCD(fib[i], fib[i - 1])
, wo i> 0.Entscheiden wir uns zum Beispiel für den Fall, dass die Dividende 55 und der Divisor 34 beträgt (denken Sie daran, dass es sich immer noch um Fibonacci-Zahlen handelt).
Wie Sie vielleicht bemerken, kostete dieser Vorgang 8 Iterationen (oder rekursive Aufrufe).
Versuchen wir es mit größeren Fibonacci-Zahlen, nämlich 121393 und 75025. Wir können auch hier feststellen, dass 24 Iterationen (oder rekursive Aufrufe) erforderlich waren.
Sie können auch feststellen, dass jede Iteration eine Fibonacci-Zahl ergibt. Deshalb haben wir so viele Operationen. Wir können ähnliche Ergebnisse nicht nur mit Fibonacci-Zahlen erzielen.
Daher wird die Zeitkomplexität diesmal durch ein kleines Oh (Obergrenze) dargestellt. Die Untergrenze ist intuitiv Omega (1): Fall von 500 geteilt durch 2 zum Beispiel.
Lösen wir die Wiederholungsrelation:
Wir können dann sagen, dass die euklidische GCD höchstens eine log (xy) -Operation ausführen kann .
quelle
Das finden Sie im Wikipedia-Artikel .
Es hat sogar eine schöne Darstellung der Komplexität für Wertepaare.
Es ist nicht
O(a%b)
.Es ist bekannt (siehe Artikel), dass niemals mehr Schritte als die fünffache Anzahl von Ziffern in der kleineren Anzahl ausgeführt werden. Die maximale Anzahl von Schritten wächst also mit der Anzahl der Ziffern
(ln b)
. Die Kosten für jeden Schritt steigen auch mit der Anzahl der Stellen, sodass die Komplexität daran gebunden ist,O(ln^2 b)
dass b die kleinere Zahl ist. Das ist eine Obergrenze, und die tatsächliche Zeit ist normalerweise kürzer.quelle
n
?n = ln b
. Was ist die reguläre Komplexität des Moduls für Big Int? Ist es O (log n log ^ 2 log n)Siehe hier .
Insbesondere dieser Teil:
So
O(log min(a, b))
ist eine gute Obergrenze.quelle
Hier ist ein intuitives Verständnis der Laufzeitkomplexität des Euclid-Algorithmus. Die formalen Beweise werden in verschiedenen Texten wie Einführung in Algorithmen und TAOCP Vol 2 behandelt.
Denken Sie zuerst darüber nach, was wäre, wenn wir versuchen würden, gcd von zwei Fibonacci-Zahlen F (k + 1) und F (k) zu nehmen. Sie können schnell feststellen, dass der Euklid-Algorithmus zu F (k) und F (k-1) iteriert. Das heißt, mit jeder Iteration bewegen wir uns in der Fibonacci-Reihe um eine Zahl nach unten. Da Fibonacci-Zahlen O (Phi ^ k) sind, wobei Phi der goldene Schnitt ist, können wir sehen, dass die Laufzeit von GCD O (log n) war, wobei n = max (a, b) und log die Basis von Phi hat. Als nächstes können wir beweisen, dass dies der schlimmste Fall ist, indem wir beobachten, dass Fibonacci-Zahlen konsistent Paare erzeugen, bei denen die Reste in jeder Iteration groß genug bleiben und niemals Null werden, bis Sie am Anfang der Serie angekommen sind.
Wir können O (log n), wobei n = max (a, b) gebunden ist, noch enger machen. Angenommen, b> = a, damit wir gebunden an O schreiben können (log b). Beobachten Sie zunächst, dass GCD (ka, kb) = GCD (a, b) ist. Da die größten Werte von k gcd (a, c) sind, können wir b in unserer Laufzeit durch b / gcd (a, b) ersetzen, was zu einer engeren Grenze von O führt (log b / gcd (a, b)).
quelle
Der schlimmste Fall des Euklid-Algorithmus ist, wenn die Reste bei jedem Schritt so groß wie möglich sind, d. H. für zwei aufeinanderfolgende Terme der Fibonacci-Sequenz.
Wenn n und m die Anzahl der Stellen von a und b sind, wobei n> = m angenommen wird, verwendet der Algorithmus O (m) -Divisionen.
Beachten Sie, dass die Komplexität immer in Bezug auf die Größe der Eingaben angegeben wird, in diesem Fall in Bezug auf die Anzahl der Ziffern.
quelle
Der schlimmste Fall tritt auf, wenn sowohl n als auch m aufeinanderfolgende Fibonacci-Zahlen sind.
gcd (Fn, Fn - 1) = gcd (Fn - 1, Fn - 2) = ⋯ = gcd (F1, F0) = 1 und die n-te Fibonacci-Zahl ist 1,618 ^ n, wobei 1,618 der goldene Schnitt ist.
Um gcd (n, m) zu finden, ist die Anzahl der rekursiven Aufrufe Θ (logn).
quelle
Hier ist die Analyse im Buch Datenstrukturen und Algorithmusanalyse in C von Mark Allen Weiss (zweite Ausgabe, 2.4.4):
Hier ist der Code:
Hier ist ein Satz , den wir verwenden werden:
BEWEIS:
Wir können also folgende Schlussfolgerung ziehen:
quelle
Der Satz von Gabriel Lame begrenzt die Anzahl der Schritte durch log (1 / sqrt (5) * (a + 1/2)) - 2, wobei die Basis des log (1 + sqrt (5)) / 2 ist. Dies ist das Worst-Case-Szenario für den Algorithmus und tritt auf, wenn die Eingaben aufeinanderfolgende Fibanocci-Zahlen sind.
Eine etwas liberalere Grenze ist: log a, wobei die Basis des log (sqrt (2)) von Koblitz impliziert wird.
Für kryptografische Zwecke berücksichtigen wir normalerweise die bitweise Komplexität der Algorithmen, wobei berücksichtigt wird, dass die Bitgröße ungefähr durch k = loga gegeben ist.
Hier ist eine detaillierte Analyse der bitweisen Komplexität des Euklid-Algorithmus:
Obwohl in den meisten Referenzen die bitweise Komplexität des Euklid-Algorithmus durch O (loga) ^ 3 gegeben ist, gibt es eine engere Grenze, die O (loga) ^ 2 ist.
Erwägen; r0 = a, r1 = b, r0 = q1.r1 + r2. . . , ri-1 = qi.ri + ri + 1 ,. . . , rm-2 = qm-1.rm-1 + rm rm-1 = qm.rm.
Beachten Sie Folgendes: a = r0> = b = r1> r2> r3 ...> rm-1> rm> 0 .......... (1)
und rm ist der größte gemeinsame Teiler von a und b.
Durch eine Behauptung in Koblitz 'Buch (Ein Kurs in Zahlentheorie und Kryptographie) kann bewiesen werden, dass: ri + 1 <(ri-1) / 2 ................. ( 2)
Wiederum in Koblitz wird die Anzahl der Bitoperationen, die erforderlich sind, um eine positive k-Bit-Ganzzahl durch eine positive l-Bit-Ganzzahl (unter der Annahme von k> = l) zu teilen, wie folgt angegeben: (k-l + 1) .l ...... .............(3)
Nach (1) und (2) ist die Anzahl der Teilungen O (loga), und nach (3) ist die Gesamtkomplexität O (loga) ^ 3.
Dies kann nun durch eine Bemerkung in Koblitz auf O (loga) ^ 2 reduziert werden.
Betrachten Sie ki = logri +1
durch (1) und (2) haben wir: ki + 1 <= ki für i = 0,1, ..., m-2, m-1 und ki + 2 <= (ki) -1 für i = 0 , 1, ..., m-2
und durch (3) sind die Gesamtkosten der m Divisionen begrenzt durch: SUMME [(ki-1) - ((ki) -1))] * ki für i = 0,1,2, .., m
Neuordnung: SUM [(ki-1) - ((ki) -1))] * ki <= 4 * k0 ^ 2
Die bitweise Komplexität von Euklids Algorithmus ist also O (loga) ^ 2.
quelle
Für den iterativen Algorithmus haben wir jedoch:
Bei Fibonacci-Paaren gibt es keinen Unterschied zwischen
iterativeEGCD()
unditerativeEGCDForWorstCase()
wo letzteres wie folgt aussieht:Ja, mit Fibonacci-Paaren
n = a % n
undn = a - n
es ist genau das Gleiche.Wir wissen auch, dass in einer früheren Antwort auf dieselbe Frage ein abnehmender Faktor vorherrscht:
factor = m / (n % m)
.Um die iterative Version der euklidischen GCD in einer definierten Form zu gestalten, können wir daher Folgendes als "Simulator" darstellen:
Basierend auf der Arbeit (letzte Folie) von Dr. Jauhar Ali ist die obige Schleife logarithmisch.
Ja, klein Oh, weil der Simulator höchstens die Anzahl der Iterationen angibt . Nicht-Fibonacci-Paare würden eine geringere Anzahl von Iterationen benötigen als Fibonacci, wenn sie auf euklidischer GCD untersucht würden.
quelle
Bei jedem Schritt gibt es zwei Fälle
b> = a / 2, dann macht a, b = b, a% b b höchstens die Hälfte seines vorherigen Wertes
b <a / 2, dann macht a, b = b, a% b höchstens die Hälfte seines vorherigen Wertes, da b kleiner als a / 2 ist
Bei jedem Schritt reduziert der Algorithmus mindestens eine Zahl auf mindestens die Hälfte weniger.
In höchstens O (log a) + O (log b) wird dies auf die einfachen Fälle reduziert. Was einen O (log n) -Algorithmus ergibt, wobei n die Obergrenze von a und b ist.
Ich habe es hier gefunden
quelle