피보나치 수는
F(0)= 0,F(1)= 1일 때, 1 이상의n에 대하여F(n)=F(n-1)+F(n-2)가 적용되는 수 입니다.
2 이상의n이 입력되었을 때,n번째 피보나치 수를 1234567으로 나눈 나머지를 리턴하는 함수,solution을 완성해 주세요.
public class FibonacciCalculator
{
private const int DIVISOR = 1234567;
public int Solution(int n)
{
int answer = 0;
Dictionary<int, int> cache = new Dictionary<int, int>();
cache.Add(0, 0);
cache.Add(1, 1);
long result = CalculateFibonacci(n, cache);
return (int)result;
}
private int CalculateFibonacci(int n, Dictionary<int, int> cache)
{
if (cache.ContainsKey(n))
{
return cache[n];
}
int fibNMinus1 = CalculateFibonacci(n-1, cache);
int fibNMinus2 = CalculateFibonacci(n-2, cache);
int currentFib = (fibNMinus1 + fibNMinus2) % DIVISOR;
cache.Add(n, currentFib);
return currentFib;
}
}
F(n) = F(n-1) + F(n-2)라는 명시된 방식대로 연산을 수행할 경우 n이 매우 커졌을 때 재귀 방식으로 연산 할 경우 기본 스택 크기를 초과하는 부하가 가해질 수 있음private const int DIVISOR = 1234567;
1234567이라는 값은 변하지 않는 상수이므로 클래스 전역에서 사용하도록 선언 private int CalculateFibonacci(int n, Dictionary<int, int> cache)
{
if (cache.ContainsKey(n))
{
return cache[n];
}
int fibNMinus1 = CalculateFibonacci(n-1, cache);
int fibNMinus2 = CalculateFibonacci(n-2, cache);
int currentFib = (fibNMinus1 + fibNMinus2) % DIVISOR;
cache.Add(n, currentFib);
return currentFib;
}
Dictionary<int, int> cache를 통해 기존에 연산한 값에 대해서는 cache 찾아 반환하도록 하는 메모이제이션(Memoization) 방식을 활용Ex)
F(5)=F(4)+F(3)
=F(4)+F(2)+F(1)
=F(3)+F(2)+F(2)+F(1)
- 더 큰 숫자들에 대해서도 이러한 과정이 반복되므로 값을 저장한 것을 활용할 수 있음
DIVISOR로 나눈 나머지를 계산하는 것이 목적이므로 cache에 값을 저장할 때부터 나머지를 연산
F(5)=F(4)+F(3)=
→F(5)%DIVISOR= (F(1)+F(1)+F(1)+F(1)+F(1)) %DIVISOR
int 저장 범위를 초과하는 것도 방지할 수 있음