publicstaticvoidmain(String[] args)throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int N = Integer.parseInt(br.readLine()); System.out.println(fibonacci(N)); }
privatestaticlongfibonacci(int n){ // 1. 우선 재귀를 그만둘 수 있는 기저 조건 // n이 0, 1일때 결과값은 0과 1이기 때문에 return n을 주었습니다. if (n <= 1) { return n; } // 그렇다면 계속 파생조건을 주어야 겠죠. return fibonacci(n - 1) + fibonacci(n - 2); } }
계산이 어떻게 이루지는지 한번 보도록하겠습니다.
1 2 3 4 5 6 7 8 9 10 11
N에 4를 입력했을 경우, 1. fibonacci(4) 함수 호출 2. n <= 1 아니기 때문에 return fibonacci(4 - 1) + fibonacci(4 - 2) 중에 첫번째 fibbonacci(4 - 1) 함수 호출 3. n <= 1 아니기 때문에 return fibonacci(3 - 1) + fibonacci(3 - 2) 중에 첫번째 fibbonacci(3 - 1) 함수 호출 4. n <= 1 아니기 때문에 return fibonacci(2 - 1) + fibonacci(2 - 2) 중에 첫번째 fibbonacci(2 - 1) 함수 호출 5. n <= 1 이기때문에 return 1; 반환 후 4. 단계에서 두번째 fibonacci(2 - 2) 함수 호출 (현재 결과 값 1) 6. n <= 1 이기때문에 return 0; 반환 후 3. 단계에서 두번째 fibonacci(3 - 2) 함수 호출 (현재 결과 값 1) 7. n <= 1 이기때문에 return 1; 반환 후 2. 단계에서 두번째 fibonacci(4 - 2) 함수 호출 (현재 결과 값 2) 8. n <= 1 아니기 때문에 return fibonacci(2 - 1) + fibonacci(2 - 2) 중에 첫번째 fibbonacci(2 - 1) 함수 호출 9. n <= 1 이기때문에 return 1; 반환 후 8. 단계에서 두번째 fibonacci(2 - 2) 함수 호출 (현재 결과 값 3) 10. n <= 1 이기때문에 return 0; 반환 후 최종 결과 값 3 반환
이해가 가지 않을 수 있습니다. 눈으로 보는 것 보다, 그리고 머리로 생각하는 것 보다 손으로 한번 써보는게 더 기억에 잘 남는다고 하니 한번 손으로 작성해보는 것도 좋은 방법인듯 합니다.
자! 여기서 잠깐… 혹시 N의 입력 값에 42이상의 값을 입력 해보셨나요? 결과 값이 조금 늦게 나오지 않았나요? 음 늦게 나오지않았다면 정말 좋은 컴퓨터를 사용중이시네요 그럼 100을 입력해보시죠 하루를 걸려서라도 결과값은 나오지 않을거에요…
이거 왜이러는 걸까요?
그림을 한번 볼까요?
함수안에서 같은 함수를 호출(재귀)하게되면 콜스택에 쌓이게 됩니다. 그렇다면 위 그림을 비교해서 보자면 fibonacci(5) 즉, 5번째는 어떤 피보나치 수가 될지 확인해보기 위해서는 fibonacci(0)을 3번, fibonacci(1)을 5번, fibonacci(2)을 3번 … 이렇게 앞에 구했던 함수를 계속해서 함수 호출을 통해 5번째 피보나치 수를 구할 수 있게 됩니다.
그렇다면 이미 구했다면 더 이상 구하지 않게 하기 위해서는 어떤 방법이 필요할까요? 바로 Memoization! 을 이용하면 되겠습니다.