Inilah jawaban yang berjalan dengan memori konstan, dengan mengorbankan CPU. Ini bukan jawaban yang baik dalam konteks pertanyaan awal (yaitu jawaban saat wawancara). Tetapi jika wawancaranya panjang 24 jam, maka itu tidak terlalu buruk. ;)
Idenya adalah bahwa jika saya memiliki n yang merupakan jawaban yang valid, maka selanjutnya dalam urutan akan n kali beberapa kekuatan dua, dibagi dengan beberapa kekuatan 5. Atau yang lain n kali kekuatan 5, dibagi dengan kekuatan dua. Asalkan terbagi rata. (... atau pembagi bisa 1;) dalam hal ini Anda hanya mengalikan 2 atau 5)
Misalnya, untuk beralih dari 625 ke 640, kalikan dengan 5 ** 4/2 ** 7. Atau, lebih umum, kalikan dengan beberapa nilai 2 ** m * 5 ** n
untuk beberapa m, n di mana satu positif dan satu negatif atau nol, dan pengali membagi angka secara merata.
Sekarang, bagian yang sulit adalah menemukan pengganda. Tetapi kita tahu a) pembagi harus membagi bilangan secara merata, b) pengali harus lebih besar dari satu (angka terus meningkat), dan c) jika kita memilih pengali terendah lebih besar dari 1 (yaitu 1 <f <semua f ), maka itu dijamin menjadi langkah kita selanjutnya. Langkah setelah itu akan menjadi langkah terendah.
Bagian yang jahat adalah menemukan nilai m, n. Hanya ada log (n) kemungkinan, karena hanya ada begitu banyak 2 atau 5 untuk menyerah, tetapi saya harus menambahkan faktor -1 hingga +1 sebagai cara ceroboh untuk menangani pembulatan. Jadi kita hanya perlu beralih melalui O (log (n)) setiap langkah. Jadi itu adalah O (n log (n)) secara keseluruhan.
Berita baiknya adalah, karena mengambil nilai dan menemukan nilai berikutnya, Anda dapat mulai dari mana saja dalam urutan. Jadi, jika Anda ingin yang berikutnya setelah 1 miliar, itu hanya dapat menemukannya dengan mengulangi 2/5 atau 5/2 dan memilih pengganda terkecil yang lebih besar dari 1.
(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
Saya memvalidasi 10.000 angka pertama yang dihasilkan ini dibandingkan 10.000 pertama yang dihasilkan oleh solusi daftar yang diurutkan, dan berfungsi setidaknya sejauh itu.
BTW yang berikutnya setelah satu triliun tampaknya menjadi 1.024.000.000.000.
...
Hm Saya bisa mendapatkan kinerja O (n) - O (1) per nilai (!) - dan O (log n) penggunaan memori dengan memperlakukan best()
sebagai tabel pencarian yang diperluas secara bertahap. Saat ini menghemat memori dengan mengulangi setiap kali, tapi itu melakukan banyak perhitungan yang berlebihan. Dengan memegang nilai-nilai menengah - dan daftar nilai min - saya dapat menghindari pekerjaan duplikat & mempercepatnya banyak. Namun, daftar nilai-nilai perantara akan tumbuh dengan n, maka memori O (log n).