นี่คือคำตอบที่ทำงานด้วยหน่วยความจำคงที่โดยมีค่าใช้จ่ายของ CPU นี่ไม่ใช่คำตอบที่ดีในบริบทของคำถามเดิม (เช่นคำตอบในระหว่างการสัมภาษณ์) แต่ถ้าการสัมภาษณ์ยาว 24 ชั่วโมงมันก็ไม่เลว ;)
แนวคิดก็คือถ้าฉันมี n ซึ่งเป็นคำตอบที่ถูกต้องดังนั้นลำดับต่อไปจะเท่ากับ n คูณกำลังสอง, หารด้วยพลัง 5 หรือมิฉะนั้น n คูณกำลัง 5, หารด้วย a พลังของสอง ให้มันแบ่งเท่า ๆ กัน (... หรือตัวหารสามารถเป็น 1;) ซึ่งในกรณีนี้คุณแค่คูณด้วย 2 หรือ 5)
ตัวอย่างเช่นหากต้องการจาก 625 ถึง 640 ให้คูณด้วย 5 ** 4/2 ** 7. หรือโดยทั่วไปแล้วคูณด้วยค่าบางค่าของ2 ** m * 5 ** n
บาง m, n โดยที่หนึ่งเป็นบวกและหนึ่งเป็นลบหรือศูนย์และ ตัวคูณหารจำนวนอย่างเท่าเทียมกัน
ตอนนี้ส่วนที่ยุ่งยากคือการหาตัวคูณ แต่เรารู้ว่า a) ตัวหารต้องหารจำนวนอย่างเท่าเทียมกัน b) ตัวคูณต้องมากกว่าหนึ่ง (ตัวเลขเพิ่มขึ้นเรื่อย ๆ ) และ c) ถ้าเราเลือกตัวคูณต่ำสุดที่มากกว่า 1 (เช่น 1 <f อื่น ๆ ทั้งหมดของ f ) จากนั้นรับประกันได้ว่าจะเป็นขั้นตอนต่อไปของเรา ขั้นตอนหลังจากนั้นจะเป็นขั้นตอนที่ต่ำที่สุด
ส่วนที่น่ารังเกียจคือการหาค่าของ m, n มีเพียงความเป็นไปได้ในการบันทึก (n) เพราะมีเพียง 2 หรือ 5 เท่านั้นที่จะยอมแพ้ แต่ฉันต้องเพิ่มปัจจัยที่ -1 ถึง +1 เป็นวิธีเลอะเทอะเพื่อจัดการกับ roundoff ดังนั้นเราต้องทำซ้ำผ่าน O (log (n)) แต่ละขั้นตอน ดังนั้นจึงเป็น O (n log (n)) โดยรวม
ข่าวดีก็คือเพราะมันต้องใช้ค่าและหาค่าต่อไปคุณสามารถเริ่มต้นได้ทุกที่ในลำดับ ดังนั้นหากคุณต้องการหนึ่งถัดไปหลังจาก 1 พันล้านมันก็สามารถหาได้โดยวนซ้ำ 2/5 หรือ 5/2 และเลือกตัวคูณที่เล็กที่สุดที่มากกว่า 1
(งูใหญ่)
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
ฉันตรวจสอบความถูกต้อง 10,000 หมายเลขแรกที่สิ่งนี้สร้างขึ้นจาก 10,000 รายการแรกที่สร้างขึ้นโดยโซลูชันรายการที่เรียงลำดับและทำงานได้อย่างน้อยที่สุด
BTW หนึ่งถัดไปหลังจากล้านล้านดูเหมือนจะ 1,024,000,000,000
...
ฮึ่ม ฉันสามารถรับประสิทธิภาพ O (n) - O (1) ต่อค่า (!) - และการใช้หน่วยความจำ O (log n) โดยbest()
ถือเป็นตารางการค้นหาที่ฉันขยายเพิ่มขึ้นทีละส่วน ตอนนี้มันช่วยประหยัดหน่วยความจำด้วยการวนซ้ำทุกครั้ง แต่มันทำการคำนวณซ้ำซ้อนมากมาย โดยการเก็บค่ากลางเหล่านั้น - และรายการค่าต่ำสุด - ฉันสามารถหลีกเลี่ยงการทำงานซ้ำ ๆ และเพิ่มความเร็วได้มาก อย่างไรก็ตามรายการของค่ากลางจะเพิ่มขึ้นด้วย n ดังนั้นหน่วยความจำ O (log n)