이 간단한 코드를 설명하십시오 :
public int fibonacci(int n) {
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
마지막 줄과 혼동됩니다. 특히 예를 들어 n = 5 인 경우 fibonacci (4) + fibonacci (3) 등이 호출되지만이 알고리즘이 인덱스 5의 값을 계산하는 방법을 이해하지 못하기 때문에 방법. 자세하게 설명 해주세요!
답변
피보나치 수열에서 각 항목은 이전 두 항목의 합계입니다. 따라서 재귀 알고리즘을 작성했습니다.
그래서,
fibonacci(5) = fibonacci(4) + fibonacci(3)
fibonacci(3) = fibonacci(2) + fibonacci(1)
fibonacci(4) = fibonacci(3) + fibonacci(2)
fibonacci(2) = fibonacci(1) + fibonacci(0)
이제는 이미 알고 fibonacci(1)==1 and fibonacci(0) == 0
있습니다. 따라서 나중에 다른 값을 계산할 수 있습니다.
지금,
fibonacci(2) = 1+0 = 1
fibonacci(3) = 1+1 = 2
fibonacci(4) = 2+1 = 3
fibonacci(5) = 3+2 = 5
그리고 피보나치 수열에서 0,1,1,2,3,5,8,13,21....
우리는 5th element
피보나치 수열이을 반환 한다는 것을 알 수 있습니다 5
.
재귀 자습서는 여기를 참조하십시오 .
답변
코드에는 두 가지 문제가 있습니다.
- 결과는 정수 채우기 마이너스 비트 이후 첫 48 피보나치 수만 처리 할 수있는 int에 저장되며 결과는 잘못됩니다.
- 그러나 피보나치 (50)를 실행할 수 없습니다.
코드
fibonacci(n - 1) + fibonacci(n - 2)
가 매우 잘못되었습니다.
문제는 피보나치가 50 번이 아니라 훨씬 더 많다는 것입니다.
처음에는 피보나치 (49) + 피보나치 (48),
다음 피보나치 (48) + 피보나치 (47) 및 피보나치 (47) + 피보나치 (46)
라고합니다. 피보나치 (n)가 될 때마다 복잡성이 지수입니다.
비 재귀 코드에 대한 접근 방식 :
double fibbonaci(int n){
double prev=0d, next=1d, result=0d;
for (int i = 0; i < n; i++) {
result=prev+next;
prev=next;
next=result;
}
return result;
}
답변
의사 코드에서 n = 5 인 경우 다음이 발생합니다.
피보나치 (4) + 피보나치 (3)
이것은 다음과 같이 분류됩니다.
(피보나치 (3) + 피보나치 (2)) + (피보나치 (2) + 피보나치 (1))
이것은 다음과 같이 분류됩니다.
(((피보나치 (2) + 피보나치 (1)) + ((피보나치 (1) + 피보나치 (0))) + ((((피보나치 (1) + 피보나치 (0)) + 1))
이것은 다음과 같이 분류됩니다.
((((피보나치 (1) + 피보나치 (0)) + 1) + ((1 + 0)) + ((1 + 0) + 1))
이것은 다음과 같이 분류됩니다.
((((1 + 0) + 1) + ((1 + 0)) + ((1 + 0) + 1))
결과 : 5
피보나치 수열이 1 1 2 3 5 8 … 이면 5 번째 요소는 5입니다. 동일한 방법론을 사용하여 다른 반복을 알아낼 수 있습니다.
답변
재귀는 때때로 파악하기 어려울 수 있습니다. 적은 수의 종이로 그것을 평가하십시오.
fib(4)
-> fib(3) + fib(2)
-> fib(2) + fib(1) + fib(1) + fib(0)
-> fib(1) + fib(0) + fib(1) + fib(1) + fib(0)
-> 1 + 0 + 1 + 1 + 0
-> 3
Java가 실제로 이것을 어떻게 평가하는지 잘 모르겠지만 결과는 같습니다.
답변
다음과 같이 기능을 단순화 할 수도 있습니다.
public int fibonacci(int n) {
if (n < 2) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
답변
F(n)
/ \
F(n-1) F(n-2)
/ \ / \
F(n-2) F(n-3) F(n-3) F(n-4)
/ \
F(n-3) F(n-4)
중요한 점은이 알고리즘은 이전 계산 된 숫자의 결과를 저장하지 않기 때문에 지수입니다. 예를 들어 F (n-3)은 3 번 호출됩니다.
자세한 내용은 dasgupta chapter 0.2의 알고리즘을 참조하십시오.
답변
대부분의 답은 좋고 피보나치의 재귀가 어떻게 작동하는지 설명합니다.
다음은 재귀를 포함하는 세 가지 기술에 대한 분석입니다.
- 루프
- 재귀
- 메모
다음은 세 가지를 모두 테스트하는 코드입니다.
public class Fibonnaci {
// Output = 0 1 1 2 3 5 8 13
static int fibMemo[];
public static void main(String args[]) {
int num = 20;
System.out.println("By For Loop");
Long startTimeForLoop = System.nanoTime();
// returns the fib series
int fibSeries[] = fib(num);
for (int i = 0; i < fibSeries.length; i++) {
System.out.print(" " + fibSeries[i] + " ");
}
Long stopTimeForLoop = System.nanoTime();
System.out.println("");
System.out.println("For Loop Time:" + (stopTimeForLoop - startTimeForLoop));
System.out.println("By Using Recursion");
Long startTimeRecursion = System.nanoTime();
// uses recursion
int fibSeriesRec[] = fibByRec(num);
for (int i = 0; i < fibSeriesRec.length; i++) {
System.out.print(" " + fibSeriesRec[i] + " ");
}
Long stopTimeRecursion = System.nanoTime();
System.out.println("");
System.out.println("Recursion Time:" + (stopTimeRecursion -startTimeRecursion));
System.out.println("By Using Memoization Technique");
Long startTimeMemo = System.nanoTime();
// uses memoization
fibMemo = new int[num];
fibByRecMemo(num-1);
for (int i = 0; i < fibMemo.length; i++) {
System.out.print(" " + fibMemo[i] + " ");
}
Long stopTimeMemo = System.nanoTime();
System.out.println("");
System.out.println("Memoization Time:" + (stopTimeMemo - startTimeMemo));
}
//fib by memoization
public static int fibByRecMemo(int num){
if(num == 0){
fibMemo[0] = 0;
return 0;
}
if(num ==1 || num ==2){
fibMemo[num] = 1;
return 1;
}
if(fibMemo[num] == 0){
fibMemo[num] = fibByRecMemo(num-1) + fibByRecMemo(num -2);
return fibMemo[num];
}else{
return fibMemo[num];
}
}
public static int[] fibByRec(int num) {
int fib[] = new int[num];
for (int i = 0; i < num; i++) {
fib[i] = fibRec(i);
}
return fib;
}
public static int fibRec(int num) {
if (num == 0) {
return 0;
} else if (num == 1 || num == 2) {
return 1;
} else {
return fibRec(num - 1) + fibRec(num - 2);
}
}
public static int[] fib(int num) {
int fibSum[] = new int[num];
for (int i = 0; i < num; i++) {
if (i == 0) {
fibSum[i] = i;
continue;
}
if (i == 1 || i == 2) {
fibSum[i] = 1;
continue;
}
fibSum[i] = fibSum[i - 1] + fibSum[i - 2];
}
return fibSum;
}
}
결과는 다음과 같습니다.
By For Loop
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
For Loop Time:347688
By Using Recursion
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
Recursion Time:767004
By Using Memoization Technique
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
Memoization Time:327031
따라서 우리는 메모가 가장 현명 하고 루프 일치와 밀접하게 일치 하는 것을 볼 수 있습니다 .
그러나 재귀가 가장 오래 걸리므로 실제 생활에서 피해야 할 수도 있습니다. 또한 재귀를 사용하는 경우 솔루션을 최적화해야합니다.