피보나치 함수를 구하는 문제이다
보통 피보나치 수열은 재귀함수를 이용해서 구할 수 있다.
def fibo(x):
if x == 1 or x == 2:
return 1
else:
return fibo(x-1) + fibo(x-2)
이런 식으로 구할 수 있는데
문제는 숫자가 조금만 커지게되면 연산횟수가 급격하게 증가하고 그에 따라서 속도도 엄청 느려지게 된다.
이런 문제를 메모이제이션(재귀함수이용) 또는 반복문을 이용해서 해결할 수 있다.
메모이제이션은 이미 한번 연산을 했던 값은 따로 저장해뒀다가 필요할때마다 찾아서 쓴다는 아이디어다.
말 그대로 따로 메모해둔다고 생각하면 된다.
반복문을 이용하는 방법은 작은 문제부터 하나하나씩 풀어나가는 방법이다.
결론적으로는 선형시간의 시간복잡도를 갖는다.
코드로 살펴보자.
- 바텀업 방식(반복문 이용)
# 1003번 피보나치 함수
# 바텀업
import sys
input = sys.stdin.readline
t = int(input())
number = [[0,0]] * (101)
def fibo(n):
number[0] = [1,0]
number[1] = [0,1]
if n >= 2:
for i in range(2,n+1):
a = number[i-1][0] + number[i-2][0]
b = number[i-1][1] + number[i-2][1]
number[i] = [a,b]
return number[n]
for _ in range(t):
n = int(input())
number = [[0,0]] * (101)
f = fibo(n)
print(f[0],f[1])
- 탑다운 방식(재귀 이용)
def fibo_memo(x):
if x == 0:
memo[x] = [1,0]
return memo[x]
elif x == 1:
memo[x] = [0,1]
return memo[x]
elif x in memo:
return memo[x]
else:
a = fibo_memo(x-1)[0] + fibo_memo(x-2)[0]
b = fibo_memo(x-1)[1] + fibo_memo(x-2)[1]
memo[x] = [a,b]
return memo[x]
import sys
input = sys.stdin.readline
t = int(input())
for _ in range(t):
n = int(input())
memo = {}
f = fibo(n)
print(f[0],f[1])
기본적으로 두 방법 모두 선형시간의 시간복잡도를 갖기 때문에 두가지 방법 모두 통과가 되었다.
바텀업방식은 반복문을 이용해서 작은 문제부터 풀어나가는 것이,
탑다운방식은 큰 문제에서 하나하나 쪼개면서 푸는데 분할한 작은 문제들을 어디에 따로 메모한다는 것이 핵심포인트이다.
728x90
'알고리즘 문제풀이 > Dynamic programming' 카테고리의 다른 글
백준 1932 파이썬(DP) (0) | 2021.10.12 |
---|---|
백준 1149 파이썬(DP) (0) | 2021.10.11 |
백준 9416 파이썬(DP) (0) | 2021.10.10 |
백준 1904 파이썬(DP) (0) | 2021.10.10 |
백준 9184 파이썬(DP - 메모이제이션) (0) | 2021.10.09 |