BOJ 백준 [2748] 피보나치 수

2019. 9. 12. 00:02Algorithm/ 백준 온라인 저지

문제 설명


 일반적으로 피보나치 수를 이용하여 문제를 해결하려고 해보면,   

1
2
3
4
5
6
7
int getFibo(int n) {
    if (n<=1) {
        return n;
    }
    
    return getFibo(n-1+ getFibo(n-2);
}
Colored by Color Scripter

위와 같이 간단한 재귀함수를 생각해낼 것이다. 하지만, 위의 코드의 경우 n의 최댓값이 90이므로, 

주어진 n에서 최댓값이 주어질 경우 해당 피보나치 수는 int의 최댓값을 넘을 것이다. 

 --> long long 자료형을 사용해 주자.

그리고 시간 복잡도의 경우 2^n이므로 최악의 경우 2^90 = 1,237,940,039,285,380,274,899,124,224‬ 이므로,

1초의 시간을 넘어 서게 된다. 위의 경우, 어떻게 문제를 해결해야 할까?


IDEA 1

for 문으로 탐색해서 피보나치 값을 구해보자.

1
2
3
4
5
6
7
8
9
10
if(n <= 1) {
    printf("%d", n);
else {
    for(int i=2 ; i <= n ; i++) {
        ans = prev_1 + prev_2;
        prev_2 = prev_1;            
        prev_1 = ans;
    }
    printf("%lld",ans);
}                    

위와 같이 for문을 이용해서 문제를 해결한다면 O(n)의 시간내에 해결이 가능하다.

 


IDEA 2

만약 재귀함수로 문제를 해결하고 싶다면, 메모제이션 기법을 이용하여 문제를 해결해보자.

메모제이션 기법을 사용하면 반복적으로 사용되는 데이터가 도출되기까지 연산을 하는 과정이있다면, 이를 저장해 놓음으로서 여러번 반복적인 연산을 하지 않게 할 수 있다.

 

1
2
3
4
5
6
7
8
unsigned long long fibo[100];
 
unsigned long long Get_Fibo(int n) {
    if (n <= 1return fibo[n];
    if (fibo[n] != -1)return fibo[n];
    fibo[n] = Get_Fibo(n - 1+ Get_Fibo(n - 2);
    return fibo[n];
}
Colored by Color Scripter

만약, fibo배열이 -1로 초기화 되어 있다고 생각해보자. 이미 연산을 한 값에 대해서는 기록된 값을 사용하면 되므로 위에서 여러번 반복적으로 연산하여 2^n의 시간이 들게 한 것을 n의 시간으로 줄일 수 있다.