6. Рефакторинг функции Фибоначчи
Условие задачи:
🔥 Дана рекурсивная реализация функции Фибоначчи.
Необходимо провести рефакторинг, улучшить производительность и оценить сложность.
Исходный код:
// n: 0, 1, 2, 3, 4, 5, ...
// f: 0, 1, 1, 2, 3, 5, 8, 13, ...
int fib(int n) {
if (n <= 1) return n;
return fib(n-1) + fib(n-2);
}
Спойлеры к решению
Подсказки
💡 Текущая реализация имеет экспоненциальную сложность O(2^n).
💡 Проблема — многократные повторные вычисления одинаковых значений.
💡 Можно использовать:
Итеративный подход (самый простой и эффективный).
Мемоизацию (кэширование).
💡 Итеративная версия имеет сложностьO(n)и памятьO(1).
💡 Не забудь проверить входное значениеn < 0.
Решение
1️⃣ Итеративное решение (оптимальное)
public class Fibonacci {
public static int fib(int n) {
if (n < 0) {
throw new IllegalArgumentException("n must be >= 0");
}
if (n <= 1) {
return n;
}
int prev = 0;
int curr = 1;
for (int i = 2; i <= n; i++) {
int next = prev + curr;
prev = curr;
curr = next;
}
return curr;
}
public static void main(String[] args) {
System.out.println(fib(5)); // 5
System.out.println(fib(10)); // 55
}
}
⏱ Сложность:
Время: O(n)
Память: O(1)
2️⃣ Вариант с мемоизацией (если нужен рекурсивный стиль)
import java.util.HashMap;
import java.util.Map;
public class FibonacciMemo {
private static final Map<Integer, Integer> cache = new HashMap<>();
public static int fib(int n) {
if (n < 0) {
throw new IllegalArgumentException("n must be >= 0");
}
if (n <= 1) {
return n;
}
if (cache.containsKey(n)) {
return cache.get(n);
}
int result = fib(n - 1) + fib(n - 2);
cache.put(n, result);
return result;
}
}
⏱ Сложность:
Время: O(n)
Память: O(n) (кэш + стек рекурсии)
📌 Что важно помнить:
✅ Исходная версия имеет сложность O(2^n) — очень медленная.
✅ Итеративная реализация — самая практичная.
✅ Мемоизация убирает дублирующие вычисления.
✅ Для больших n лучше использовать long или BigInteger.
✅ На собеседовании важно уметь объяснить, почему исходный код неэффективен.