[Algorithm] 다이나믹 프로그래밍

곽호택·2021년 8월 2일
0

알고리즘

목록 보기
7/9
post-thumbnail
post-custom-banner

! 이진 탐색까지 끝나고 이제 다이나믹 프로그래밍에 대해 공부한 내용을 정리해봤다.

1. 다이나믹 프로그래밍이란?

큰 문제를 작게 나누고, 같은 문제일 경우 한 번씩만 풀어 문제를 효율적으로 해결하는 알고리즘 기법

다이나믹 프로그래밍(Dynamic Programming)은 동적 계획법이라고 표현하기도 한다.

2가지 방식이 있는데 바로 탑다운보텀업이다. 추가적으로 이 책에서는 메모이제이션 기법까지 소개되어있다.

다이나믹 프로그래밍 기법 문제의 대표적인 예시는 바로 피보나치 수열이다.

피보나치 수열의 경우는 이전 두항의 합이 현재의 항으로 설정되는 수열이다.

예를 들면
1 1 2 3 5 8 13 21 ... 이런 식으로 이전 두 항 1+1 이 3번째 항 2가 되고,
다음 1 + 2가 4번째 항 3이되며 이런 방식으로 계속 반복이 이루어진다.

이 피보나치 수열의 경우 점화식으로 표현이 가능하다.

수학적 점화식을 프로그래밍으로 표현하려면 재귀 함수를 이용하면 된다.

- 피보나치 함수 코드

def fibo(x):
	if x == 1 or x == 2:
    		return 1
    	return fibo(x - 1) + fibo(x - 2)
   	

하지만 우리가 다음과 같이 피보나치 함수 코드를 사용할 경우 시간 복잡도에 심각한 문제가 발생하게 된다.

위의 그림을 보면 f(3)함수가 반복적으로 호출되는 것이 보인다. 이미 계산을 했음에도 호출 될 때마다 계산하는 것이다.

일반적으로 피보나치 함수의 시간복잡도는 O(2^n)으로 N=30일 경우 약 10억 가량의 연산을 수행해야한다. 시간이 너무 오래 걸린다!!

하지만 이러한 문제는 다이나믹 프로그래밍을 사용할 경우 효율적으로 해결이 가능하다.😁

하지만 항상 다이나믹 프로그래밍을 사용할 수는 없고, 조건을 만족할 때 사용이 가능하다.

  • 큰 문제를 작은 문제로 나눌 수 있다.

  • 작은 문제에서 구한 정답은 그것을 포함하는 큰 문제에서도 동일하다.

피보나치 수열은 이 조건에 해당하며, 다이나믹 프로그래밍의 메모이제이션 기법을 통해 다시 구현해보자.

- 메모제이션기법이란?

다이나믹 프로그래밍을 구현하는 방법 중에 한 종류로, 한 번 구한 결과를 메모리 공간에 메모해두고 같은 식을 다시 호출할 경우 메모한 결과를 그대로 가져오는 기법이다. 또 다른 말로 캐싱이라고도 한다.

우리는 리스트에 정보를 저장해서 이를 수행한다.

- 메모제이션 코드 구현

d = [0] * 100		#메모제이션을 위한 리스트 초기화

def fibo(x):
	if x == 1 or x == 2:
    		return 1
    
   	if d[x] != 0:		# 이미 계산한적 있는 문제일 경우 반환
    		return d[x]
    
    d[x] = fibo(x-1) + fibo(x-2)
    return d[x]

사실 큰 문제를 작게 나누는 방법은 우리가 앞서 배웠던 정렬 중 퀵 정렬도 비슷한 맥락이다. 이러한 알고리즘은 분할 정복(Divide and Conquer)로 분류된다.

그렇다면 다이나믹 프로그래밍과 분할 정복의 차이는 무엇이냐?
바로 다이나믹 프로그래밍은 문제들이 서로 영향을 미친다는 것이다.

퀵 정렬의 경우 한 번 기준 원소가 자리를 변경해서 결정될 경우 그 기준 원소의 위치는 다시 바뀌지 않고 그 피벗값을 다시 처리하는 부분 문제는 존재하지 않는다.

하지만 다이나믹 프로그래밍의 경우에는 한 번 해결했던 문제를 다시금 해결한다! 그렇기에 메모제이션 기법과 같이 리스트에 저장해 놓는 것이 아닌가

2. 탑다운 & 보텀업

앞서 말했듯이 다이나믹 프로그래밍에는 탑다운 방식과 보텀업 방식이 있는데

  • 탑다운 방식(상향식) : 큰 문제를 해결하기 위해 작은 문제를 호출
    재귀함수를 사용한다.

  • 보텀업 방식(하향식) : 작은 문제부터 차근차근 답을 도출
    반복문을 사용한다.

우리가 위에 구현했던 방식은 탑다운 방식으로 보텀업 방식을 사용하면 다음과 같다.

d = [0] * 100

d[1] = 1
d[2] = 2
n = 99

for i in range(3, n+1):
	d[i] = d[i-1] + d[i-2]
    

다이나믹 프로그래밍의 전형적인 형태는 보텀업 방식이다. 이때 사용되는 결과 저장용 리스트는(여기서는 d)에 경우 'DP 테이블'이라고 불린다.

메모제이션의 경우는 탑다운 방식에서 사용되는 표현이다.


이상 다이나믹 프로그래밍 정리 끝!
profile
잘하고싶다
post-custom-banner

0개의 댓글