Я просто попытался реализовать код (в Java) для различных способов, с помощью которых можно вычислить n-й член последовательности Фибоначчи, и я надеюсь проверить, что я узнал.Big-O для различных реализаций Фибоначчи
Итерационный реализация выглядит следующим образом:
public int iterativeFibonacci(int n)
{
if (n == 1) return 0;
else if (n == 2) return 1;
int i = 0, j = 1, sum = 0;
for (; (n-2) != 0; --n)
{
sum = i + j;
i = j;
j = sum;
}
return sum;
}
Рекурсивная реализация выглядит следующим образом: -
public int recursiveFibonacci(int n)
{
if (n == 1) return 0;
else if (n == 2) return 1;
return recursiveFibonacci(n-1) + recursiveFibonacci(n-2);
}
memoized реализация выглядит следующим образом: -
public int memoizedFibonacci(int n)
{
if (n <= 0) return -1;
else if (n == 1) return 0;
else if (n == 2) return 1;
if (memory[n-1] == 0)
memory[n-1] = memoizedFibonacci(n-1);
if (memory[n-2] == 0)
memory[n-2] = memoizedFibonacci(n-2);
return memory[n-1]+memory[n-2];
}
Я m, имея немного сомнений при попытке выяснить Big-O этих реализаций. Я считаю, что итеративная реализация должна быть O (n), поскольку она проходит через N-2 раза.
В рекурсивной функции есть значения, пересчитанные, поэтому я думаю, что это O (n^2).
В memoized функции доступно более половины значений на основе memoization. Я читал, что алгоритм - это O (log N), если для уменьшения проблемного пространства требуется сокращение времени на долю, а - алгоритм O (N), если требуется постоянное время, чтобы уменьшить проблемное пространство на постоянное количество. Правильно ли я полагаю, что мемориальная реализация - O (n) по сложности? Если да, не будет ли итеративная реализация лучшей среди всех трех? (так как он не использует дополнительную память, требуемую памятью).
Проблемы с линейной рекурсией, подобные этим в соревнованиях по программированию, обычно решаются посредством «экспоненциальной матрицы». В этом блоге (например, http://fusharblog.com/solving-linear-recurrence-for-programming-contest/) есть пример C++ для серии Fibonacci. – plesiv