optimal substructure
- 최적 부분 구조를 가진다overlapping sub-problems
- 겹치는 작은 부분 문제가 존재 한다f(0) = 0
f(1) = 1
f(n) = f(n - 1) + f(n - 2) (n >= 2)
피보나치에서는 n번째 피보나치 수를 구하게 될때 n - 1과 n - 2 이 겹치는 작은 부분 문제가 존재하고 있다. 재귀를 사용하거나 n번까지 for loop로 값을 구할 수 있다
재귀(recursive)
를 사용해서 푼다int fibonacci(int n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
해당 재귀 코드를 개선을 하여 메모리제이션을 이용하게 되면 다음과 같습니다. 메모리제이션이란 같은 문제는 구할때마다 중복해서 계산하지 않기 위해 배열에 저장되는 것을 말합니다.
int[] dp = new int[n + 1];
int fibonacci(int n) {
if (n <= 1) {
return n;
}
if (dp[n] > 0) {
return dp[n];
}
return dp[n] = fibonacci(n - 1) + fibonacci(n - 2);
}
메모리제이션을 사용하여 dp[n]의 값을 검증하여 존재 여부를 확인하여 바로 리턴하면 됩니다. 이렇게 되면 모든 문제를 각 한번씩만 풀어서 함수의 시간복잡도가 줄어들게 됩니다.
int fibonacci(int n) {
int[] dp = new int[n + 1];
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
둘중 하나에서 자신있는 것으로 하되, top-down, down-up 둘다 사용할 수 있도록 공부하여야 하며 점화식으로 정의를 해야 합니다.