✅ 동적계획법 (Dynamic Programming)
❕ 기본 개념
- 복잡한 문제를 간단한 여러 개의 문제로 나누어 푸는 방법
- 일반적인 재귀 방식과 매우 유사하지만, 작은 문제들이 여러번 반복되는 비효율적인 계산을 피할 수 있음
해당 알고리즘이 필요한 문제의 조건은 아래와 같다.
1. 겹치는 부분 문제 (Overlapping Subproblems)
: DP는 문제를 작은 문제들로 나누고 그 결과값들을 재활용해서 전체 답을 구한다. 따라서 동일한 부분 문제들이 반복하여 나타나고, 부분 문제가 중복되는 경우에 사용 가능하다.
2. 최적 부분 구조 (Optimal Substructure)
: 부분 문제의 최적 결과 값을 사용해 전체 문제의 최적해를 낼 수 있는 경우를 의미한다.
❕ 작동 방식
DP를 통해 시간복잡도는 O(n2) → O(f(n))으로 개선됨
✔ 활용 예시
- 최장 공통 부분 수열: 두 개 이상의 수열의 공통 부분수열 중 가장 긴 수열을 찾는 알고리즘
- 배낭 문제: 조합 최적화
- 벨먼-포드 알고리즘
- 다익스트라 알고리즘: 시작점과 다른 점들 사이의 최단경로를 찾아내는 알고리즘
✔ 문제 예시
- 피보나치 수열
- 최단 경로 문제
✔ 구현 방법 (JS)
1. Top-down with Memoization
const fibWithMemo = (n) => {
let memo = {}; // we will store("memoize") our values here
const fib = (n) => {
let value;
if (n in memo) {
// if the n is already in our memo object, we look it up and store it in value
value = memo[n];
} else {
// otherwise, we calculate it and store it in value
if (n === 1 || n === 2) {
value = 1;
} else {
value = fib(n - 1) + fib(n - 2);
}
// store the value for current n to our memo object
memo[n] = value;
}
console.log(memo);
return value;
};
return fib(n);
};
2. Bottom-up with Tabulation
const fibWithTab = (n) => {
if (n === 1 || n === 2) return 1;
// initialize an array and store the values we already know
let fibNums = [0, 1, 1];
// loop starting at index 3 (first value we do not know) until n
for (let i = 3; i <= n; i++) {
// store values in the array at Nth index
fibNums[i] = fibNums[i - 1] + fibNums[i - 2];
}
return fibNums[n];
};
참고자료
https://ko.wikipedia.org/wiki/동적_계획법
https://hongjw1938.tistory.com/47
https://www.geeksforgeeks.org/dynamic-programming/
https://medium.com/swlh/demystifying-dynamic-programming-b22d65095866
'Devlog > DS & Algorithms' 카테고리의 다른 글
[알고리즘] 이진 탐색 (0) | 2022.08.16 |
---|---|
[알고리즘] Greedy Algorithm (0) | 2022.08.06 |
[알고리즘] 계수 정렬 (0) | 2022.08.06 |
[알고리즘] 퀵 정렬 (0) | 2022.08.05 |
[알고리즘] 삽입 정렬 (0) | 2022.08.05 |