Определение fibonaci (n):
fibonacci (n) = fibonacci (n-1) + fibonacci (n-2)
Наивная реализация на Haskell
fibonacci :: Integer -> Integer
fibonacci 0 = 1
fibonacci 1 = 1
fibonacci x = fibonacci (x-1) + fibonacci (x-2)
Все формулы можно проследить до этого определения, некоторые из которых работают очень быстро, а некоторые очень медленно. В приведенной выше реализации O (n) = 2 ^ n
В духе вашего вопроса, позвольте мне убрать использование списков и дать вам то, что работает в O (n) Т.е. давайте не будем держать все фибоначчи от 0 до n в списке.
Если у нас есть тройка (кортеж из трех членов), который выглядит так:
(n, fibonacci[n-1], fibonacci[n])
Помня первоначальное определение, мы можем вычислить следующую тройку из последней тройки:
(n+1, fibonacci[n], fibonacci[n-1] + fibonacci[n])
= (n+1, fibonacci[n], fibonacci[n+1])
И следующая тройка из последней тройки: (n+2, fibonacci[n+1], fibonacci[n] + fibonacci[n+1])
= (n+1, fibonacci[n+1], fibonacci[n+2])
И так далее ...
n = 0 => (0,0,1)
n = 1 => (1,1,1) - calculated from the previous triple
n = 2 => (2,1,2) - calculated from the previous triple
n = 3 => (3,2,3) - calculated from the previous triple
n = 4 => (4,3,5) - calculated from the previous triple
n = 5 => (5,5,8) - calculated from the previous triple
Давайте реализуем это в Haskell и будем использовать понятные имена переменных:
nextTripleIfCurrentNIsLessThanN :: (Int, Integer, Integer) -> Int -> (Int, Integer, Integer)
nextTripleIfCurrentNIsLessThanN (currentN, x, y) n = if currentN < n
then nextTripleIfCurrentNIsLessThanN (currentN + 1, y, x + y) n
else (currentN, x, y)
thirdElementOfTriple :: (x,y,z) -> z
thirdElementOfTriple (x,y,z) = z
fibonacci :: Int -> Integer
fibonacci n = thirdElementOfTriple (nextTripleIfCurrentNIsLessThanN (0,0,1) n)
Это будет работать в O (n) [Это умеренно квадратично, что проявляется в больших количествах. Причина в том, что добавление больших чисел обходится дороже, чем добавление маленьких. Но это отдельное обсуждение модели вычислений.]
fibonacci 0
1
fibonacci 1
1
fibonacci 2
2
fibonacci 3
3
fibonacci 4
5
fibonacci 5
8
fibonacci 5000
6276302800488957086035253108349684055478528702736457439025824448927937256811663264475883711527806250329984690249846819800648580083040107584710332687596562185073640422286799239932615797105974710857095487342820351307477141875012176874307156016229965832589137779724973854362777629878229505500260477136108363709090010421536915488632339240756987974122598603591920306874926755600361865354330444681915154695741851960071089944015319300128574107662757054790648152751366475529121877212785489665101733755898580317984402963873738187000120737824193162011399200547424034440836239726275765901190914513013217132050988064832024783370583789324109052449717186857327239783000020791777804503930439875068662687670678802914269784817022567088069496231111407908953313902398529655056082228598715882365779469902465675715699187225655878240668599547496218159297881601061923195562143932693324644219266564617042934227893371179832389642895285401263875342640468017378925921483580111278055044254198382265567395946431803304304326865077742925818757370691726168228648841319231470626
person
galeaspablo
schedule
09.11.2017
fibSerie a b = a : (fibSerie b (a+b))
, а затем:fibs = fibSerie 1 1
. - person jpmarinier   schedule 26.07.2019ω = 2 + min ω (ω - 1)
.zipWith
создает здесь (бесконечный) список целых чисел, а не только одно целое число, так что это не2 + 1
общие элементы, а2 + ω
. то естьω
. - person Will Ness   schedule 20.08.2019