Ответ сильно зависит от вашей реализации.В приведенном вами примере есть несколько возможных решений, и я бы сказал, что наивный способ реализации решения имеет большую сложность, когда реализован итеративно.Вот две реализации:
int iterative_fib(int n) {
if (n <= 2) {
return 1;
}
int a = 1, b = 1, c;
for (int i = 0; i < n - 2; ++i) {
c = a + b;
b = a;
a = c;
}
return a;
}
int recursive_fib(int n) {
if (n <= 2) {
return 1;
}
return recursive_fib(n - 1) + recursive_fib(n-2);
}
В обеих реализациях я предположил правильный ввод, т.е. n> = 1. Первый код намного длиннее, но его сложность O (n), то есть линейная, а вторая реализациякороче, но имеет экспоненциальную сложность O (fib (n)) = O (φ ^ n) (φ = (1+√5)/2
) и, следовательно, намного медленнее.Можно улучшить рекурсивную версию, введя запоминание (т. Е. Запоминание возвращаемых значений функции, которую вы уже вычислили).Обычно это делается путем введения массива, в котором вы храните значения.Вот пример:
int mem[1000]; // initialize this array with some invalid value. Usually 0 or -1
// as memset can be used for that: memset(mem, -1, sizeof(mem));
int mem_fib(int n) {
if (n <= 2) {
return mem[n] = 1;
}
if (mem[n-1] == -1) {
solve(n-1);
}
if (mem[n-2] == -1) {
solve(n-2);
}
return mem[n] = mem[n-1] + mem[n-2];
}
Здесь сложность рекурсивного алгоритма линейна, как итеративное решение.Решение, которое я представил выше, является нисходящим подходом для динамического программирования решения вашей проблемы.Восходящий подход приведет к чему-то очень похожему на решение, которое я представил как итеративное.Есть много статей о динамическом программировании, в том числе в википедии
В зависимости от проблем, с которыми я столкнулся в моем опыте, некоторые из них гораздо сложнее решить с помощью подхода «снизу вверх» (т.е. итеративное решение)в то время как другие трудно решить с нисходящим подходом.Однако теория утверждает, что каждая задача, имеющая итеративное решение, имеет рекурсив с той же вычислительной сложностью (и наоборот).
Надеюсь, этот ответ поможет.