Der "Hacker" im Namen des Tests schlägt vor, dass wir versuchen, eine rechnerorientierte Lösung zu finden.
Beginnen wir daher mit einem Programm zur Brute-Force-Aufzählung von (a) den "günstigen" Fällen, in denen eine ganze Zahl doppelt so groß ist wie die andere, und (b) allen möglichen Fällen. Die Antwort wäre dann ihr Verhältnis. Ich habe eine allgemeine Lösung codiert. Seine Eingabe ist eine positive ganze Zahl n
und seine Ausgabe ist die Wahrscheinlichkeit.
n=100
all=favorable=0
for i=1 to n
for j=1 to n
if (i != j) all=all+1 {1}
if (j == 2*i) favorable = favorable+1 {2}
if (i == 2*j) favorable = favorable+1 {3}
return(favorable / all)
(Der Beweis der Richtigkeit beruht auf der Tatsache, dass für jede positive Zahl .)i≠2ii
Dieses Programm erfordert Tests und bis zu Inkremente für jede Iteration der inneren Schleife. Daher sind bei jeder Ausführung der inneren Schleife zwischen und Berechnungen erforderlich , oder insgesamt bis . Das ist Leistung: OK für kleine wie , aber schrecklich, wenn oder so überschreitet .333n6n3n26n2O(n2)nn=100n10000
Als Hacker möchten Sie als Erstes die quadratische Leistung eliminieren, indem Sie die innere Schleife vereinfachen (falls möglich). Gehen Sie zu diesem Zweck systematisch die Zeilen in der inneren Schleife (wie nummeriert) durch und beachten Sie Folgendes:
Zeile 1 wird für jeden Wert von i
bis auf einmal ausgeführt und daher mal all
inkrementiert . Folglich kann für die Berechnung von die Schleife durch Inkrementieren um ersetzt werden .n−1all
j
all
n-1
Zeile 2 wird genau einmal ausgeführt, wenn und ansonsten überhaupt nicht. Daher kann es durch Inkrementieren um wenn .2i≤nall
12i≤n
Zeile 3 wird ausgeführt, sobald sie gerade i
ist.
Hier ist das transformierte Programm.
n=100
all=favorable=0
for i=1 to n
all = all + (n-1) {1'}
if (2*i <= n) favorable = favorable+1 {2'}
if (even(i)) favorable = favorable+1 {3'}
return(favorable / all)
Können wir weiter gehen und seine Schleife beseitigen?
Zeile 1 'wird mal ausgeführt. Daher wird um erhöht .nall
n*(n-1)
Zeile 2 'wird nur ausgeführt, wenn . Eine Möglichkeit, dies zu zählen, ist (die größte Ganzzahl kleiner oder gleich ).2i≤n⌊n/2⌋n/2
Zeile 3 'wird nur für gerade Werte von . Wiederum passiert das times.⌊ n / 2 ⌋i⌊n/2⌋
Die zweite Transformation des Programms ist:
n=100
all=favorable=0 {0}
all = all + n * (n-1) {1''}
favorable = favorable + floor(n/2) {2''}
favorable = favorable + floor(n/2) {3''}
return(favorable / all)
Dies ist bereits eine enorme Leistung: Ein -Algorithmus wurde auf einen -Algorithmus reduziert (der als "geschlossene Formel" für die Antwort angesehen werden kann).O ( 1 )O(n2)O(1)
Schließlich gibt es einige einfache algebraische Transformationen, die wir durchführen können, indem wir die Initialisierung (Zeile 0) in die erste Verwendung jeder Variablen rollen und die Zeilen 2 '' und 3 '' kombinieren:
n=100
all = n * (n-1)
favorable = 2 * floor(n/2)
return(favorable / all)
Zu diesem Zeitpunkt könnte ein Mensch das Programm ausführen. Machen wir es mit :n=100
all = 100 * (100-1) = 100*99
favorable = 2 * floor(100/2) = 2*50 = 100
favorable/all = 100 / (100*99) = 1/99
Die Ausgabe ist daher .1/99
Zusammenfassend kann ein Brute-Force-Algorithmus mithilfe einfacher Programmumschreibungsregeln systematisch in ein elegantes -Programm umgewandelt werden.O(1)