Нахождение суммы последовательного подмассива Фибоначчи

#python #optimization #fibonacci

Вопрос:

У нас есть входное целое число, скажем, 13. Мы можем найти последовательный подмассив чисел Фибоначчи, который суммируется с 10 — [2,3,5]. Мне нужно найти следующее число, которое не является суммой последовательного подмассива. В данном случае это число будет равно 14. У меня есть этот код, но загвоздка в том, что его можно оптимизировать, чтобы не перебирать все N начиная с указателя влево = 1 и указателя вправо = 1, а каким-то образом «импортировать» из предыдущего N, и я понятия не имею, как это сделать, так что, возможно, кто-то поумнее может помочь.

 def fib(n):  if n == 1: return 1  if n == 2: return 1  return fib(n-1)   fib(n-2)   def fibosubarr(n):  L_pointer = 1  R_pointer = 2  sumfibs = 1  while sumfibs != n:   if sumfibs gt; n and L_pointer lt; R_pointer:  sumfibs -= fib(L_pointer)  L_pointer  = 1   elif sumfibs lt; n and L_poiner lt; R_pointer:  sumfibs  = fib(R_pointer)  R_pointer  = 1   else: return False  return True   n = int(input())  while fibosubarr(n):  n  = 1 print(n)  

Комментарии:

1. Да, ваш код очень расточителен. Вы должны построить весь ряд Фибоначчи до вашего целевого числа (этого более чем достаточно, но это нормально) и сохранить его в списке, а не воссоздавать его каждый раз. Используйте этот список ( fib[n] ) вместо вызова функции ( fib(n) ).

Ответ №1:

Вот техника, называемая «запоминание». fib Функция здесь отслеживает текущий список и расширяет его только по мере необходимости. Как только он сгенерировал номер, ему не нужно делать это снова.

 _fib = [1,1] def fib(n):  while len(_fib) lt;= n:  _fib.append( _fib[-2] _fib[-1] )  return _fib[n]  

С вашей схемой 200000 вызвали заметную задержку. С помощью этой схемы даже 2 миллиарда запускаются мгновенно.

Ответ №2:

Чтобы получить следующую сумму подмножества, вам нужен только один вызов функции-при условии, что вы отслеживаете наименьшее значение суммы, которое было превышено n .

Я бы также использовал генератор чисел Фибоначчи:

 def genfib():  a = 1  b = 1  while True:  yield b  a, b = b, a   b  def fibosubarr(n):  left = genfib()  right = genfib()   sumfibs = next(right)  closest = float("inf")  while sumfibs:  if sumfibs gt; n:  closest = min(sumfibs, closest)  sumfibs -= next(left)  elif sumfibs lt; n:  sumfibs  = next(right)  else:  return n  return closest  

Теперь вы можете сделать то, что вы сделали-вывести следующую допустимую сумму, которая является, по крайней мере, входным значением:

 n = int(input()) print(fibosubarr(n))  

Вы также можете циклически переходить от одной такой суммы к другой:

 n = 0 for _ in range(10): # first 10 such sums  n = fibosubarr(n 1)  print(n)