Algorithmen und Komplexität Lösungsvorschlag zu Übungsblatt 1

Werbung
ETH Zürich
Institut für Theoretische Informatik
Prof. Dr. Angelika Steger
Florian Meier, Ralph Keusch
HS 2016
Algorithmen und Komplexität
Lösungsvorschlag zu Übungsblatt 1
Lösungsvorschlag zu Aufgabe 1
(a) Ja, da limn→∞
ln n
log2 n
= ln 2.
(b) Nein, da lim supn→∞
(c) Ja, da lim supn→∞
lim
n→∞
n!
nn
n
log2 n
= ∞.
= limn→∞
n·(n−1)····1
n·n····n
≤ limn→∞
1
n
= 0. Via
dn/2e bn/2c
n!
1
dn/2e
n
1 dn/2e
≤
lim
≤
lim
+
n→∞ 2
n→∞
nn
n
n
n
(oder mit der Stirling-Formel) sieht man sogar dass der Limes exponentiell gegen 0 geht.
(d) Nein, siehe (c).
(e) Nein, da lim supn→∞
(f) Ja, da limn→∞
1/n
1
22n
2n
= lim supn→∞ 2n = ∞.
= 0.
Lösungsvorschlag zu Aufgabe 2
Das folgende Programm verdoppelt die Zahlen in den Speicherzellen M1 , . . . , Mn :
Eingabe: n natürliche Zahlen in M1 , . . . , Mn sowie M0 = n.
Ausgabe: Die Zahlen in M1 , . . . , Mn verdoppelt.
1: M−2 ← 1
2: M−1 ← M M0
3: M−1 ← M−1 + M−1
4: M M0 ← M−1
5: M0 ← M0 − M−2
6: GOTO 2 IF M0 > 0.
Die Zahl in M0 sagt uns, wieviele Zahl wir verdoppeln müssen. Wir starten bei Mn und kopieren
in Befehlszeile 2 die Zahl von Mn nach M−1 . Dort wird sie verdoppelt, anschliessend überschreiben wir Mn mit dem neuen Wert. Wir haben Mn somit verdoppelt, machen unseren Zähler in M0
um eins kleiner und fahren danach mit Mn−1 fort. Dieses Prozedere wiederholen wir solange bis
M0 = 0. Dann sind alle Zahlen verdoppelt und das Programm ist fertig.
Lösungsvorschlag zu Aufgabe 3
Wir betrachten die beiden Algorithmen zuerst im Einheitskostenmodell. Es bezeichne L(n) die
Laufzeit von Algorithmus F IB A für die Eingabe n. Aufgrund der rekursiven Definition gilt dann
L ( n ) = L ( n − 1) + L ( n − 2) + 1
(die 1 entspricht der Addition der beiden vorhergehenden Fibonacci-Zahlen), wobei
L(0) = L(1) = O(1) .
1
(1)
Man sieht, dass L(n) selbst einer Fibonacci-ähnlichen Rekursionsgleichung folgt und mindestens
so schnell wächst wie Fn . Für n ≥ 1 gilt die untere Schranke
n −2
3
Fn ≥
,
2
wie man leicht mittels vollständiger Induktion zeigt: Als Induktionsschritt haben wir
Fn+1 = Fn + Fn−1 ≥
n −1
n −2 n −3 n −3 3
3
3
3
3
+
=
+1 ≥
;
2
2
2
2
2
als Induktionsanfang F (1) = 1 ≥
3 −1
2
=
2
3
und F (2) = 1 ≥
3 0
= 1.
2
3 n
2 , d.h. exponentiell. Ganz genau
Die Laufzeit von F IB A wächst also mindestens so schnell wie
könnte man durch Lösen √
der inhomogenen Differenzengleichung (1) zeigen, dass die Laufzeit
Θ(Φn ) ist, wobei Φ = 1+2 5 ≈ 1.61 („Goldener Schnitt“). Dies hängt natürlich zusammen mit
der expliziten Darstellung der Fibonacci-Folge Fn = √1 (Φn − (1 − Φ)n ), welche man als Lösung
5
der zu (1) zugehörigen homogenen Differenzengleichung erhält. Die Laufzeit von F IB A wächst
also gleich schnell wie die Fibonacci-Zahlen selbst.
Nun zu F IB B. Hier wird die FOR-Schleife (n − 1)-mal, d.h. O(n)-mal durchlaufen, wo bei in
jedem Durchlauf konstant viele, d.h. O(1) Operationen ausgeführt werden. Wir erhalten also
eine Laufzeit von O(n) · O(1) = O(n) für F IB B. Man entscheidet sich deshalb für F IB B.
Die Laufzeit lässt sich weiter verbessern, indem man die Identität
n 1 1
Fn+1
Fn
=
1 0
Fn
Fn−1
ausnutzt: Wenn n eine Zweierpotenz ist, reicht es, die Matrix log n-mal zu quadrieren. Da jede
dieser log n Matrixmultiplikationen eine konstante Anzahl an Additionen und Multiplikationen
benötigt, ergibt sich im Einheitskostenmodell eine totale Laufzeit von O(log n). (Die Aussage gilt
auch, wenn n keine Zweierpotenz ist - warum?)
Soweit die Rechnung im Einheitskostenmodell. Leider haben wir bei der ganzen Sache gemogelt:
die Fibonaccizahl Fn ist exponentiell viel grösser als die Eingabe n, d.h., wir haben die “ungeschriebenen Regeln” verletzt. Diese besagen, dass wir in einer Speicherzelle nur polynomial beschränkte Zahlen abspeichern dürfen, d.h. Zahlen, die kleiner sind als nk für ein beliebiges aber
festes k. Schauen wir uns also noch die Laufzeitanalyse an, wenn die Anzahl Bitoperationen gezählt wird:
Die Laufzeit von F IB A folgt nun der Rekursion
L(n) = L(n − 1) + L(n − 2) + O(log Fn )
= L(n − 1) + L(n − 2) + O(n) ,
da der Zeitbedarf für die Addition der zwei vorhergehenden Fibonaccizahlen nun proportional
zur Anzahl involvierter Bits ist und die Fibonacci-Zahlen wie erwähnt exponentiell schnell wachsen. Er ergibt sich immer noch eine Laufzeit von O(Φn ) (dies gilt selbst dann, wenn statt O(n)
ein beliebiges Polynom steht).
Für F IB B überlegen wir uns, dass wir O(n) Additionen ausführen, von denen die i-te O(log Fi ) =
O(i ) Bitoperationen benötigt. Als Gesamtlaufzeit ergibt sich
n
∑ O(i) = O
i =1
2
n2 .
Der Trick mit dem sukzessiven Quadrieren einer Matrix führt im Bitkostenmodell zu keiner direkten Verbesserung der Laufzeit: Die Länge der involvierten Zahlen verdoppelt
sich in jedem
Schritt, d.h. beim i-ten Mal Quadrieren haben die Matrixeinträge O 2i Bits, und das Quadrie
ren mittels normaler schriftlicher Multiplikation benötigt O 2i O 2i = O 4i Bitoperationen.
Durch Summation einer geometrischen Reihe ergibt sich eine Laufzeit von
log n
∑
O 4i = O 4log n = O n2 .
i =1
Der Schönhage-Strassen-Algorithmus (1971) kann zwei Zahlen der Länge n in O(n log n log log n)
Bitoperationen multiplizieren. Wenn dieser Algorithmus für das iterative Quadrieren der Matrix
verwendet wird, ergibt sich analog eine Laufzeit von
log n
∑
i =1
log n O 2i log 2i log log 2i = O(log n log log n) ∑ O 2i = O(n log n log log n)
i =1
für die Berechnung der n-ten Fibonacci-Zahl, d.h. quasilineare Laufzeit in Bitoperationen(!). Allerdings ist die Konstante, die sich hinter dem O(. . . ) verbirgt, sehr gross, so dass dieser Algorithmus nicht unbedingt der für praktische Zwecke bestgeeignetste ist.
3
Herunterladen