Veröffentlicht · wird verbessert
Algorithm
Teile und herrsche zerlegt ein Problem in kleinere Teilprobleme, löst sie rekursiv und kombiniert die Ergebnisse, etwa bei Mergesort oder Quickselect.
Teile und herrsche (divide and conquer) ist ein Entwurfsprinzip für Algorithmen: Ein Problem wird in kleinere Instanzen desselben Problems zerlegt (teilen), diese werden rekursiv gelöst (herrschen), und aus ihren Ergebnissen entsteht die Gesamtlösung (kombinieren). Mergesort, binäre Suche, schnelle Exponentiation, Quickselect, die Karazuba-Multiplikation und die Suche nach dem nächsten Punktpaar folgen diesem Muster.
Das Prinzip ist wichtig, weil es eine O(n^2)-Lösung durch Ausprobieren oft auf O(n log n) oder sogar O(log n) verkürzt. Der Kerngedanke, Informationen über die Teilungsgrenze hinweg im Kombinationsschritt zu berechnen, wie beim Zählen von Inversionen, taucht in Coding-Interviews immer wieder auf. Dieselben Ideen stecken in Sortierbibliotheken, der Multiplikation großer Zahlen, der FFT und der modularen Exponentiation in der Kryptografie.
Verfolgen Sie zuerst Mergesort von Hand, um Teilen, Herrschen und Kombinieren zu verinnerlichen, und üben Sie dann, Rekurrenzen wie T(n) = aT(n/b) + f(n) aufzustellen und mit dem Master-Theorem zu lösen. Implementieren Sie anschließend das Zählen von Inversionen, die schnelle Exponentiation und Quickselect selbst und lernen Sie zu erkennen, wann sich überlappende Teilprobleme stattdessen dynamische Programmierung erfordern.
Eingabe aufteilen, Teile rekursiv lösen, Ergebnisse kombinieren. Ein Basisfall beendet die Rekursion, und die Kosten des Kombinierens bestimmen meist die Laufzeit.
Die Laufzeit wird als T(n) = aT(n/b) + f(n) geschrieben; der Vergleich von f(n) mit n^(log_b a) liefert Ergebnisse wie O(n log n) für Mergesort.
Fälle, die beide Hälften berühren, in linearer Zeit zu behandeln, etwa beim Zählen von Inversionen oder beim maximalen Teilarray, ist die zentrale Idee.
Bleibt nur ein Teilproblem übrig, wie bei binärer Suche, schneller Exponentiation und Quickselect, entstehen Algorithmen mit O(log n) oder erwartet O(n).
sort_count sortiert die Liste mit Mergesort und addiert jedes Mal, wenn ein Element der rechten Hälfte zuerst übernommen wird, die Zahl der links noch wartenden Elemente; so werden Inversionen in O(n log n) gezählt. power ist schnelle Exponentiation: Der Exponent wird halbiert und das Zwischenergebnis quadriert, daher genügen O(log e) Multiplikationen. python divide_and_conquer.py gibt die sortierte Liste mit ihren 14 Inversionen und 3^200 modulo 1.000.000.007 aus.
divide_and_conquer.py
def sort_count(a):
"""Return (sorted list, number of inversions) using merge sort."""
if len(a) <= 1:
return list(a), 0
mid = len(a) // 2
left, x = sort_count(a[:mid])
right, y = sort_count(a[mid:])
merged, i, j, cross = [], 0, 0, 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
merged.append(left[i])
i += 1
else:
merged.append(right[j])
j += 1
cross += len(left) - i # right[j] is smaller than every left[i:]
merged += left[i:] + right[j:]
return merged, x + y + cross
def power(base, exp, mod):
"""base ** exp % mod with O(log exp) multiplications."""
if exp == 0:
return 1 % mod
half = power(base, exp // 2, mod)
result = half * half % mod
return result * base % mod if exp % 2 else result
if __name__ == "__main__":
print(sort_count([5, 2, 4, 7, 1, 3, 2, 6])) # ([1, 2, 2, 3, 4, 5, 6, 7], 14)
print(power(3, 200, 1_000_000_007)) # 136318165
python divide_and_conquer.pySechs Kapitel führen dich von der Installation bis zu den Kernkonzepten von Teile und herrsche.
Stelle Fragen, teile Erfahrungen und tausche Meinungen zu Teile und herrsche aus.
Noch keine Diskussionen. Starte die erste.
0 Kommentare
Anmelden · Melde dich an, um einen Kommentar zu schreiben.
Schreib den ersten Kommentar.