Пусть F1
, F2
, F3
- количество способов построения N из 1, 2 и 3, не начиная с 1, 2, 3 соответственно.
Тогда:
F1(N) = F2(N-2) + F3(N-3)
F2(N) = F1(N-1) + F3(N-3)
F3(N) = F1(N-1) + F2(N-2)
с граничными условиями:
F1(0) = F2(0) = F3(0) = 1
F1(x) = F2(x) = F3(x) = 0 (for x < 0)
Затем для решения исходной задачи: F(0) = 1
, F(N) = F1(N-1) + F2(N-2) + F3(N-3)
Линейное решение, использующее O (1) пробел:
def F(N):
a, b, c, d, e, f, g, h, i = 1, 0, 0, 1, 0, 0, 1, 0, 0
for _ in range(N-1):
a, b, c, d, e, f, g, h, i = e+i, a, b, a+i, d, e, a+e, g, h
return a+e+i
for n in range(11):
print(n, F(n))
При этом используются следующие рекуррентные отношения:
F1(i+1), F1(i), F1(i-1) = F2(i-1)+F3(i-2), F1(i), F1(i-1)
F2(i+1), F2(i), F2(i-1) = F1(i)+F3(i-2), F2(i), F2(i-1)
F3(i+1), F3(i), F3(i-1) = F1(i)+F2(i-1), F3(i), F3(i-1)
Это дает вам возможность построить Fn (i + 1), Fn (i), Fn (i).-1) из Fn (i), Fn (i-1), Fn (i-2) так же, как работает обычный алгоритм Фибоначчи с линейным временем (построение Fib (n + 1), Fib (n) из Fib(n), Fib (n-1)).Эти рекуррентные отношения кодируются в строке, которая обновляет переменные a
до i
.