Hier ist eine Antwort, die auf Kosten der CPU mit konstantem Speicher ausgeführt wird. Dies ist keine gute Antwort im Kontext der ursprünglichen Frage (dh Antwort während eines Interviews). Aber wenn das Interview 24 Stunden dauert, ist es nicht so schlimm. ;)
Die Idee ist, dass wenn ich n habe, was eine gültige Antwort ist, das nächste in der Sequenz n-mal eine Zweierpotenz sein wird, geteilt durch eine Potenz von 5. Oder n-mal eine Potenz von 5, geteilt durch a Kraft von zwei. Vorausgesetzt, es teilt sich gleichmäßig. (... oder der Divisor kann 1 sein;) In diesem Fall multiplizieren Sie nur mit 2 oder 5)
Um beispielsweise von 625 auf 640 zu gelangen, multiplizieren Sie mit 5 ** 4/2 ** 7. Oder multiplizieren Sie allgemeiner mit einem Wert von 2 ** m * 5 ** n
für einige m, n, wobei eins positiv und eins negativ oder null ist, und die Der Multiplikator teilt die Zahl gleichmäßig.
Der schwierige Teil ist nun, den Multiplikator zu finden. Wir wissen jedoch, dass a) der Divisor die Zahl gleichmäßig teilen muss, b) der Multiplikator größer als eins sein muss (die Zahlen nehmen weiter zu) und c) wenn wir den niedrigsten Multiplikator größer als 1 auswählen (dh 1 <f <alle anderen fs) ), dann ist das garantiert unser nächster Schritt. Der Schritt danach ist der niedrigste.
Der böse Teil ist das Finden des Wertes von m, n. Es gibt nur log (n) Möglichkeiten, weil es nur so viele 2er oder 5er gibt, die aufgegeben werden müssen, aber ich musste einen Faktor von -1 bis +1 hinzufügen, um schlampig mit Rundungen umzugehen. Wir müssen also nur jeden Schritt durch O (log (n)) iterieren. Es ist also insgesamt O (n log (n)).
Die gute Nachricht ist, dass Sie überall in der Sequenz beginnen können, da es einen Wert annimmt und den nächsten Wert findet. Wenn Sie also den nächsten nach 1 Milliarde möchten, können Sie ihn einfach finden, indem Sie die 2/5 oder 5/2 durchlaufen und den kleinsten Multiplikator größer als 1 auswählen.
(Python)
MAX = 30
F = - math.log(2) / math.log(5)
def val(i, j):
return 2 ** i * 5 ** j
def best(i, j):
f = 100
m = 0
n = 0
max_i = (int)(math.log(val(i, j)) / math.log(2) + 1) if i + j else 1
#print((val(i, j), max_i, x))
for mm in range(-i, max_i + 1):
for rr in {-1, 0, 1}:
nn = (int)(mm * F + rr)
if nn < -j: continue
ff = val(mm, nn)
#print(' ' + str((ff, mm, nn, rr)))
if ff > 1 and ff < f:
f = ff
m = mm
n = nn
return m, n
def detSeq():
i = 0
j = 0
got = [val(i, j)]
while len(got) < MAX:
m, n = best(i, j)
i += m
j += n
got.append(val(i, j))
#print('* ' + str((val(i, j), m, n)))
#print('- ' + str((v, i, j)))
return got
Ich habe die ersten 10.000 Zahlen, die dies generiert, gegen die ersten 10.000 validiert, die von der Lösung für sortierte Listen generiert wurden, und es funktioniert zumindest so weit.
Übrigens scheint der nächste nach einer Billion 1.024.000.000.000 zu sein.
...
Hm. Ich kann die Leistung von O (n) - O (1) pro Wert (!) - und O (log n) des Speichers erhalten, indem best()
ich sie als Nachschlagetabelle behandle, die ich schrittweise erweitere. Im Moment spart es Speicher, indem es jedes Mal wiederholt wird, aber es führt viele redundante Berechnungen durch. Indem ich diese Zwischenwerte - und eine Liste von Mindestwerten - halte, kann ich die doppelte Arbeit vermeiden und sie erheblich beschleunigen. Die Liste der Zwischenwerte wächst jedoch mit n, daher der O (log n) -Speicher.