본문 바로가기
코딩테스트/프로그래머스

[프로그래머스/java] 피보나치 수 - 동적 프로그래밍 DP(Dynamic Programming - top- down, bottom-up)

by drCode 2021. 3. 11.
728x90
반응형

이번 포스팅은 피보나치 수입니다.

 

혼자 피보나치 수를 풀어볼 때는 재귀 형식으로 문제를 풀었었습니다.

 

public static void main(String[] args) {
	int answer = finbonachi(n);
}

public int fibonachi(n) {
	if(n == 0) return 0;
    	else if(n == 1) return 1;
    	else return fibonachi(n-1) + fibonachi(n-2);
}

 

피보나치 수를 재귀적으로 호출하게 된다면 

숫자가 크면 클수록 호출되는 양이 기하급수적으로 늘어나게 됩니다.

 

따라서 이번 문제를 풀 때는 동적 프로그래밍 기법을 알아야 합니다.

 

동적 프로그래밍이란?

 :  큰 문제를 한 번에 해결하기 힘들 때 작은 여러 개의 문제로 나누어서 푸는 기법인데요. 작은 문제들을 풀다보면 같은 문제들을 반복해서 푸는 경우가 생깁니다. 그 문제들을 매번 재계산하지 않고 값을 저장해두었다가 재사용하는 기법이 동적 프로그래밍입니다.

 

동적 프로그래밍 구현 방법에는 두 가지가 있습니다.

 

(1) Top-down

Top-down은 재귀함수로 구현하는 경우가 많습니다. 

위에 작성된 피보나치 코드방식이 Top-Down 방식입니다.

  1. fib(5)
  2. fib(4) + fib(3)
  3. (fib(3) + fib(2)) + (fib(2) + fib(1))
  4. ((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
  5. (((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))

와 같은 방식으로 호출하기 때문에 fib(0), fib(1) 같은 경우는 여러번 호출됩니다.

그러면 속도가 굉장히 느려지기 때문에 효율이 떨어집니다.

 

(2) Bottom-up

Bottom-up 방식은 작은 문제부터 차례로 구해나가는 방식입니다. 

public int bottomUp(int n) {
	int[] arr = new int[n];
	arr[0] = 0; arr[1] = 1;
	if(n == 0) return arr[0];
	else if(n == 1) return arr[1];
	else {
		for(int i = 2; i < n+1; i++) arr[i] = arr[i-1] + arr[i-2];
		return arr[n];
	}
}

이렇게 배열로 선형적인 방식으로 값을 넣는데

호출 되는 것을 보면

 

n이 5일 때,

arr[0] = 0

arr[1] = 1

arr[2] = arr[0] + arr[1] = 0 + 1 = 1

arr[3] = arr[2] + arr[1] = 1 + 1 = 2

arr[4] = arr[3] + arr[2] = 2 + 1 = 3

arr[5] = arr[4] + arr[3] = 3 + 2 = 5

이렇게 됩니다.

 

애초에 배열에 값이 들어가게 되고 풀이 방식을 호출하는 것이 아닌,

메모리에 있는 값을 불러오는 것이기 때문에 시간이 덜 듭니다.

 

이와 같은 방식으로 피보나치 수 문제를 풀어보겠습니다.

 

programmers.co.kr/learn/courses/30/lessons/12945

 

 

코딩테스트 연습 - 피보나치 수

피보나치 수는 F(0) = 0, F(1) = 1일 때, 1 이상의 n에 대하여 F(n) = F(n-1) + F(n-2) 가 적용되는 수 입니다. 예를들어 F(2) = F(0) + F(1) = 0 + 1 = 1 F(3) = F(1) + F(2) = 1 + 1 = 2 F(4) = F(2) + F(3) = 1 + 2 = 3 F(5) = F(3) + F(4) =

programmers.co.kr

문제 설명

피보나치 수는 F(0) = 0, F(1) = 1일 때, 1 이상의 n에 대하여 F(n) = F(n-1) + F(n-2) 가 적용되는 수 입니다.

예를들어

  • F(2) = F(0) + F(1) = 0 + 1 = 1
  • F(3) = F(1) + F(2) = 1 + 1 = 2
  • F(4) = F(2) + F(3) = 1 + 2 = 3
  • F(5) = F(3) + F(4) = 2 + 3 = 5

와 같이 이어집니다.

2 이상의 n이 입력되었을 때, n번째 피보나치 수를 1234567으로 나눈 나머지를 리턴하는 함수, solution을 완성해 주세요.

제한 사항

* n은 1이상, 100000이하인 자연수입니다.

입출력 예

n return
3 2
5 5

입출력 예 설명

피보나치수는 0번째부터 0, 1, 1, 2, 3, 5, ... 와 같이 이어집니다.

 

package fibonachiNumber;

public class FibonachiNumber {
	public static void main(String[] args) {
		Solution s = new Solution();
		System.out.println(s.solution(3));
		System.out.println(s.solution(5));
	}
}


class Solution {
    public int solution(int n) {
    	int[] arr = new int[n+1];
    	arr[0] = 0;
    	arr[1] = 1;
    	
    	if(n == 0) return arr[0];
    	else if(n == 1) return arr[1];
    	else {
    		for (int i = 2; i < n+1; i++) arr[i] = arr[i-1] % 1234567 + arr[i-2] % 1234567;
    		return arr[n] % 1234567;
    	}
    }
}
728x90
반응형

댓글