Đây là một câu trả lời chạy với bộ nhớ không đổi, với chi phí CPU. Đây không phải là một câu trả lời tốt trong bối cảnh của câu hỏi ban đầu (tức là câu trả lời trong một cuộc phỏng vấn). Nhưng nếu cuộc phỏng vấn kéo dài 24 giờ, thì nó không quá tệ. ;)
Ý tưởng là nếu tôi có n là một câu trả lời hợp lệ, thì câu tiếp theo trong chuỗi sẽ là n lần sức mạnh của hai, chia cho một số sức mạnh bằng 5. Hoặc nếu không n nhân một sức mạnh bằng 5, chia cho a Sức mạnh của hai. Miễn là nó chia đều. (... hoặc số chia có thể là 1;) trong trường hợp bạn chỉ cần nhân với 2 hoặc 5)
Ví dụ: để đi từ 625 đến 640, nhân với 5 ** 4/2 ** 7. Hoặc, nói chung, nhân với một số giá trị của 2 ** m * 5 ** n
một số m, n trong đó một là dương và một là âm hoặc bằng 0 và số nhân chia số đồng đều.
Bây giờ, phần khó khăn là tìm số nhân. Nhưng chúng ta biết a) số chia phải chia đều số, b) số nhân phải lớn hơn một (số tiếp tục tăng) và c) nếu chúng ta chọn hệ số nhân thấp nhất lớn hơn 1 (tức là 1 <f <tất cả các f khác ), sau đó được đảm bảo là bước tiếp theo của chúng tôi. Bước sau đó sẽ là bước thấp nhất.
Phần khó chịu là tìm giá trị của m, n. Chỉ có các khả năng đăng nhập (n), vì chỉ có rất nhiều 2 hoặc 5 để từ bỏ, nhưng tôi đã phải thêm một yếu tố -1 đến +1 như một cách cẩu thả để đối phó với vòng đấu. Vì vậy, chúng tôi chỉ phải lặp qua O (log (n)) mỗi bước. Vì vậy, tổng thể O (n log (n)).
Tin tốt là, bởi vì nó lấy một giá trị và tìm giá trị tiếp theo, bạn có thể bắt đầu ở bất cứ đâu trong chuỗi. Vì vậy, nếu bạn muốn số tiếp theo sau 1 tỷ, bạn chỉ có thể tìm thấy nó bằng cách lặp qua 2/5 hoặc 5/2 và chọn hệ số nhân nhỏ nhất lớn hơn 1.
(trăn)
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
Tôi đã xác thực 10.000 số đầu tiên mà số này tạo ra so với 10.000 số đầu tiên được tạo bởi giải pháp danh sách được sắp xếp và nó hoạt động ít nhất cho đến nay.
BTW tiếp theo sau một nghìn tỷ dường như là 1.024.000.000.000.
...
Hừm. Tôi có thể nhận hiệu suất O (n) - O (1) trên mỗi giá trị (!) - và sử dụng bộ nhớ O (log n) bằng cách xử lý best()
như một bảng tra cứu mà tôi mở rộng tăng dần. Ngay bây giờ, nó tiết kiệm bộ nhớ bằng cách lặp lại mỗi lần, nhưng nó đang thực hiện rất nhiều phép tính dự phòng. Bằng cách giữ các giá trị trung gian đó - và một danh sách các giá trị tối thiểu - tôi có thể tránh được công việc trùng lặp & tăng tốc nó lên rất nhiều. Tuy nhiên, danh sách các giá trị trung gian sẽ phát triển với n, do đó bộ nhớ O (log n).