Musterlösung

Werbung
Prof. Dr. Dennis Hofheinz
Lukas Barth, Lisa Kohl
K a r l s ru h e r I n s t i t u t f ü r T e c h n o l o g i e
Institut für Theoretische Informatik
1. Übungsblatt zu Algorithmen I im SoSe 2016
https://crypto.iti.kit.edu/index.php?id=algo-sose16
{lisa.kohl,lukas.barth}@kit.edu
Musterlösungen
(O-Kalkül, 8 Punkte)
Aufgabe 1
Tragen Sie jeweils zutreffend O, Ω oder Θ in das Kästchen ein und beweisen Sie die entstandene Aussage.
Verwenden Sie wann immer möglich Θ.
a) 3n2 + 14n + 159 ∈
log2 n ∈
log n3 ,
b) log n2 ∈
2n ∈
n2 ,
n3 ,
n2 log n ∈
n3
(n + 1)! ∈
(n! + 2n )
log3 n ,
Beweisen oder widerlegen Sie die folgenden Implikationen.
c) ∀f, g : N → N : f (n) ∈ O (g(n)) ⇒ 2f (n) ∈ O 2g(n)
d) ∀k ∈ N, ∀f, g : N → N : f (n) ∈ O (g(n)) ⇒ f (n)k ∈ O g(n)k
Musterlösung:
a)
3 + 14
3n2 + 14n + 159
n +
=
lim
2
n→∞
n→∞
n
1
• Es gilt 3n2 + 14n + 159 ∈ Θ n2 , da lim
159
n2
= 3 und
3n2 + 14n + 159
< ∞.
n→∞
n2
• Es gilt 2n ∈ Ω n3 . Zu zeigen ist ∃c > 0 ∃n0 > 0 ∀n ≥ n0 : c · n3 ≤ 2n . Wir zeigen die
Aussage für c = 1 und n0 = 10 mit vollständiger Induktion:
somit 0 < lim
– Induktionsanfang: Es gilt 103 = 1000 < 1024 = 210 .
– Induktionsvoraussetzung: Für ein n ∈ N gilt n3 ≤ 2n .
– Induktionsschritt: Es gilt (n + 1)3 = n3 + 3n2 + 3n + 1 ≤ n3 + 3n2 + 3n2 + 3n2 =
IV
n>9
n3 + 9n2 < 2 · n3 ≤ 2 · 2n = 2n+1 .
• Es gilt n2 log n ∈ O n3 . Zu zeigen ist ∃c > 0 ∃n0 > 0 ∀n ≥ n0 : n2 log n ≤ c · n3 . Nach
dem vorigen Aufgabenteil gilt für alle n ≥ 10 die Ungleichung n3 ≤ 2n und damit auch
log n3 ≤ log 2n beziehungsweise 3 · log n ≤ log 2 · n. Das zeigt die gewünschte Behauptung
mit c = log3 2 und n0 = 10.
b)
log n2
2 · log n
2
= lim
=
und somit insbesondere
3
n→∞ log n
n→∞ 3 · log n
3
• Es gilt log n2 ∈ Θ log n3 , da lim
log n2
< ∞.
n→∞ log n3
0 < lim
log2 n
1
= lim
= 0.
n→∞ log3 n
n→∞ log n
• Es gilt (n + 1)! ∈ Ω (n! + 2n ). Zu zeigen ist ∃c > 0 ∃n0 > 0 ∀n ≥ n0 : c · (n! + 2n ) ≤ (n + 1)!.
Wir zeigen die Aussage für c = 1 und n0 = 2 mit vollständiger Induktion:
• Es gilt log2 n ∈ O log3 n , da lim
– Induktionsanfang: Es gilt 22 + 2! = 6 = 3!.
1
– Induktionsvoraussetzung: Für ein n ∈ N gilt n! + 2n ≤ (n + 1)!.
n≥2
IV
– Induktionsschritt: Es gilt (n + 1)! + 2n+1 = n · n! + 2 · 2n ≤ n · n! + n · 2n = n · (n! + 2n ) ≤
n · (n + 1)! < (n + 2) · (n + 1)! = (n + 2)!.
c) Die Aussage gilt nicht, ein Gegenbeispiel ist gegeben durch f : N → N, n 7→ 2n und g : N →
2n
4n
/ O(2n ), da n = 2n → ∞
N, n 7→ n. Es gilt 2n ∈ O(n), da lim
= 2, aber es gilt 22n = 4n ∈
n→∞ n
2
für n → ∞.
d) Die Aussage gilt. Wegen f (n) ∈ O(g(n)) existiert ein c > 0 und ein n0 > 0, sodass für alle n ≥ n0
gilt f (n) ≤ c · g(n). Daraus folgt, dass für alle n ≥ n0 gilt f (n)k ≤ (c · g(n)))k . D.h. für c0 = ck
und n00 = n0 folgt für alle n ≥ n00 die gewünschte Ungleichung f (n)k ≤ c0 · g(n)k .
Aufgabe 2
(Schleifeninvariante, 4 Punkte)
Gegeben sei folgender Algorithmus in Pseudocode. Gehen Sie dabei vereinfachend davon aus, dass alle
auftretenden Zahlen jeweils in eine Speicherzelle passen.
Function f (n : N) : N
a=0 : N
i=0 : N
while i < n do
b=1 : N
j=0 : N
while j < i do
b:= b + b
j:= j + 1
a:= a + b
i:= i + 1
return a
a) Berechnen Sie die Laufzeit des Algorithmus im O-Kalkül.
b) Nennen Sie eine Schleifeninvariante für die innere while-Schleife, d.h. eine Invariante, die vor, nach
und am Anfang jedes Schleifendurchlaufes gilt. Diese soll b in Abhängigkeit von j beschreiben.
c) Nennen und beweisen Sie eine Schleifeninvariante für die äußere while-Schleife. Diese soll a in
Abhängigkeit von i beschreiben. Was gibt der Algorithmus zurück?
d) Geben Sie einen optimierten Algorithmus an, der auch ausschließlich mit Additionen und Subtraktionen auskommt und die gleiche Funktion berechnet. Geben Sie die verbesserte Laufzeit im
O-Kalkül an.
Musterlösung:
a) Die innerste Schleife wird
n−1
P
i=
i=0
n(n − 1)
mal durchlaufen, damit ergibt sich eine Laufzeit in
2
Θ n2 .
b) Die Schleifeninvariante ist b = 2j .
c) Es gilt stets a = 2i − 1. Der Algorithmus gibt also die n-te Mersenne-Zahl 2n − 1 zurück. Wir
beweisen die Schleifeninvariante induktiv.
• Vor der Schleife und am Beginn des ersten Schleifendurchlaufes gilt i = 0 und a = 0 = 20 − 1.
2
• Am Anfang des i-ten Schleifendurchlaufes gelte a = 2i − 1. Wir zeigen, dass dann am Anfang
des i + 1-ten Schleifendurchlaufes a = 2i+1 − 1 gilt. Dazu betrachten wir zunächst die innere
IV
Schleife. Nach b) wird insgesamt 2i berechnet. Damit ergibt sich a = a + 2i = 2i − 1 + 2i =
2i+1 − 1.
• Da i in jedem Durchgang um einen Zähler erhöht wird und am Anfang i < n für jede
natürliche Zahl n gilt, terminiert die Schleife immer. Bei Beendigung der Schleife gilt i = n
und a = 2n − 1.
d) Der folgende Algorithmus berechnet die gleiche Funktionalität in Laufzeit Θ(n).
Function f (n : N) : N
a=1 : N
for i := 1 to n do
a:= a + a
a:= a − 1
return a
Aufgabe 3
(Karatsuba-Ofman-Multiplikation, 4 Punkte)
Multiplizieren Sie 1701 mit 8472 (das sind Dezimalzahlen!) nach dem Algorithmus von Karatsuba und
Ofman.
Hinweis: Führen Sie nur Additionen sowie einstellige Multiplikationen direkt aus. Mehrstellige Multiplikationen müssen rekursiv mit Karatsuba-Ofman berechnet werden.
Musterlösung:
Der Algorithmus:
1: Function recMult(a, b)
2:
assert a und b haben n = 2k Ziffern
3:
if n = 1 then return a · b
4:
Schreibe a als a1 · B k + a0
5:
Schreibe b als b1 · B k + b0
6:
c11 := recMult(a1 , b1 )
7:
c00 := recMult(a0 , b0 )
8:
c0110 := recMult((a1 + a0 ), (b1 + b0 ))
9:
e:= c11 · B 2k + (c0110 − c11 − c00 )B k + c00
10: return e
Schema zum Aufschrieb eines Multiplikationsaufrufs:
a·b
a1
· b1 =
recMult(a1 , b1 )
a0
· b0 =
recMult(a0 , b0 )
e
(a1 + a0 )·(b1 + b0 )=recMult((a1 + a0 ), (b1 + b0 ))
Berechnung:
Siehe Rekursionsbaum in Abbildung 1.
Aufgabe 4
(Algorithmenentwurf, 3 Punkte)
Entwerfen Sie einen Algorithmus für das folgende Problem: Gegeben sei eine Menge M von reellen
Zahlen. Eine reelle Zahl r ∈ M heißt zusammengesetzt, wenn sich r als Summe r = s + t zweier Elemente
s, t ∈ M schreiben lässt.
Entwerfen Sie einen Algorithmus in Pseudocode, der für alle r ∈ M entscheidet, ob diese zusammengesetzt
sind. Sie dürfen annehmen, dass M als aufsteigend sortiertes Array vorliegt. Ihr Algorithmus muss
asymptotisch Laufzeit O n2 haben. Begründen Sie, warum der Algorithmus diese Laufzeit erreicht.
3
1701·8472
17· 84 =1428
01· 72 = 72
18·156=2808
14410872
17·84
1428
s
HHH
HH
HH
HH
HH
HH
s
s
Hs
1· 8 = 8
7· 4 =28
8·12=96
01·72
0·7=0
1·2=2
1·9=9
72
s
96
0·1= 0
8·2=16
8·3=24
1·15
15
2808
1·15= 15
8· 6 = 48
9·21=189
s
"
"
"
"
"
"
"
"
"
"
"
"
"
s"
s
s
8·12
18·156
0·1=0
1·5=5
1·6=6
9·21
189
0·2= 0
9·1= 9
9·3=27
Abbildung 1: Berechnungsbaum
Musterlösung:
Der Algorithmus führt für jedes r ∈ M folgendes durch:
Man verwendet zwei Indizes in M, nämlich l = 0 und u = |M | − 1, die anfangs auf das größte und das
kleinste Element zeigen. Nun wird in einer Schleife geprüft: Wenn M [l] + M [u] = r, dann wird für r ja
ausgegeben und die Schleife abgebrochen. Wenn M [l] + M [u] > r, dann wird u um eins verringert. Wenn
M [l] + M [u] < r, dann wird l um eins vergrößert. Sollte zu irgendeinem Zeitpunkt u < l gelten, wird
abgebrochen und für r nein ausgegeben. Diese Schleife betrachtet jedes Element von M maximal einmal,
entsprechend
läuft die Schleife in O(n). Da es n Elemente r ∈ M gibt, ergibt sich eine Gesamtlaufzeit
2
von O n .
Der Pseudocode dazu könnte so aussehen:
A := Array of N umbers
Function isNumberComposite(n : N) :
l := 1
u := A.length
while u > l do
if A[l] + A[u] = n then
return Yes
elsif A[l] + A[u] < n then
u−−
else
l++
endif
return No
– – sorted ascendingly
– – Points to smallest currently still possible element
– – Points to largest currently still possible element
foreach n in A do
isNumberComposite(n)
4
5
Herunterladen