Grundlegende Algorithmen: Lösungshinweise


Kapitel 2

2.1
Nach jedem Vergleich wissen wir von der größeren Zahl, dass sie nicht das Minimum sein kann. Werden weniger als n-1 Vergleiche ausgeführt, so gibt es mindestens zwei Zahlen, die noch für das Minimum in Frage kommen. Wir können beide Werte im Nachinein geeignet erniedrigen, ohne dass die vorherigen Vergleiche dadurch falsch werden. Je nachdem, wie wir das tun, ist entweder die eine oder die andere das Minimum. Ein beliebiger Algorithmus mit maximal n-2 Vergleichen kann also nicht feststellen, welche der beiden nun wirklich das Minimum ist.
2.2
Erweitere den Schlüssel k des i-ten Datensatzes zu (k,i) und verwende eine lexikographische Ordnung, die auf der ersten Komponente die ursprüngliche Ordnung verwendet.
2.3
Die obere Schranke ist klar, da es maximal n(n+1)/2 Verschiebungen geben kann.
Bei n Elementen ist die Wahrscheinlichkeit, dass das letzte Element Rang k hat gerade 1/n. Somit ist die erwartete Anzahl an Verschiebungen gerade die Summe von i=0 bis i=n über i/n, was (n+1)/2 ergibt.
Per Induktion lässt sich zeigen, dass dann die erwartete Anzahl von Verschiebungen durch 1/4(n-1)2 nach unten beschränkt ist.
2.4
Es gilt.
2.5
Man kann zeigen: In der i-ten Phase wird das i-te größte Element an die richtige Position gebracht.
2.6
Man mische jeweils zwei der k Folgen zu einer neuen Folge zusammen. Man erhält dann k/2 Folgen der Länge 2n/k. Dies führt man fort, bis nur noch eine Folge übrig ist. In der i-ten Phase werden also je zwei Folgen der Länge 2i-1n/k zu einer Folge der Länge 2in/k zusammengemischt. Dabei gibt es je Phase k/2i Mischvorgänge. Insgesamt benötigt jede Phase maximal n Vergleiche und da es maximal log(k) Phasen gibt, maximal nlog(k) Vergleiche:
T(n) < k*T(n/k)+nlog(k).
Per Induktion kann man zeigen, dass T(n)=O(nlog(n)) gilt.
2.7
Mit vollständiger Induktion und Fallunterscheidung, ob n gerade oder ungerade ist. Für den Fall n ungerade ist der Beweis technisch etwas aufwendiger.
2.8
T(n)=n-1.
2.9
Man muss nur zeigen, dass innerhalb eines Levels die Knoten aufsteigend nummeriert werden und dass der linkeste Knoten eines Levels eine um eins größere Nummer als der rechteste Knoten des vorherigen Levels erhält. Dies lässt sich mit Abzählen leicht nachweisen.
2.10
Laufzeit Θ(nlog(n)).
2.11
Für k=2 ist der beschriebene Algorithmus vom Prinzip her derselbe wie Heapsort. Die Details der Implementierung weichen jedoch etwas voneinander ab.
Zu Beginn werden in den Gruppen die Minima bestimmt. Dies benötigt O(n) Vergleiche. Anschließend werden in m Gruppen von jeweils maximal k Elementen die Maxima bestimmt. Da dies etwa n Mal wiederholt wird, ergibt sich eine Laufzeit von O(nmk)=O(knlogk(n)).
Dies geht etwas effizienter für große k, wenn man nicht nur in jeder Gruppe das Minimum bestimmt, sondern die Elemente als sortiertes Feld verwaltet. Wenn man die Gruppen als Baum interpretiert, hat der Baum insgesamt O(n/k) Knoten (d.h. Gruppen). Das Sortieren aller Gruppen benötigt daher insgesamt O(n/k*klog(k)) =O(nlog(k)). Das Einfügen eines neuen Elements mittels binärer Suche in eine Gruppe kann in Zeit O(log(k)) geschehen. Somit benötigt die zweite Phase maximal Zeit O(nmlog(k)) =O(nlogk(n)log(k)) =O(nlog(n)).
2.12
Ersetze in den beiden do-while-Schleifen (array[i] < array[pivot]) bzw. (array[j] > array[pivot]) durch (array[i] ≤ array[pivot]) bzw. (array[j] ≥ array[pivot]).
2.13
Betrachte Hn als Ober- bzw. Untersumme des Integrals über dx/x mit geeigneten Grenzen.
2.14
Man rechnet nach, dass die Höhe des entstehenden Rekursionsbaumes durch log(n)/log(1/(1-ε))=O(log(n) beschränkt ist (wobei ε konstant ist). Auf jedem Level benötigen alle Partitionierungen der einzelnen Teilintervalle (die ja eine Partition von [1:n] sein müssen) maximal Zeit O(n). Somit ist der Zeitbedarf insgesamt O(nlog(n)).
2.15
Quicksort: (3,3,1,1,2); wobei das letzte Element als Pivot gewählt wird.
Heapsort: (1,2,2,2); Beachte, dass das Feld bereits die Heap-Bedingung erfüllt.
2.16
Zeige mittels vollständiger Induktion, dass Vwc(n)≥1/2(n-1)n. Dabei zeigst sich, wie die worst-case Eingabe aussieht.
2.17
Nachrechnen.
2.18
Verfahre analog zu Mergesort und teile die Folge in eine linke und rechte Folge. Bestimme rekursiv die optimalen Teilsequenzen. Die optimale Teilsequenz ergibt sich aus den beiden optimalen Lösungen der Rekursion sowie einer optimalen Folge die über den Schnittpunkt hinweggeht. Letztere kann in linearer Zeit gefunden werden.
2.19
Fleißaufgabe; Mittels lineare Suche siehe [PS] bzw. [PDF].
2.20
Fleißaufgabe
2.21
Verwende einen Entscheidungsbaum: Da es (n+m)!/(n!m!) verschiedene Lösungen gibt, ist eine untere Schranke log((n+m)!/(n!m!))