Dynamic Programming (DP) : 작은 문제의 답을 조합해 큰 문제를 푼다.

다이나믹 프로그래밍(DP)은 복잡한 문제를 여러 개의 작은 문제로 나누고, 그 작은 문제들의 결과를 재사용하여 전체 문제를 빠르게 해결하는 기법입니다.
🧠 Divide and Conquer vs Dynamic Programming
DP는 Divide and Conquer(분할 정복)와 유사해 보이지만, 몇 가지 중요한 차이점이 존재합니다.
구분Divide and ConquerDynamic Programming
문제 분할 | 주로 절반으로 나눔 | 보통 -1씩 줄여 나감 |
문제 성격 | 함수형 문제 (Function Problem) | 최적화 문제 (Optimization Problem) |
결과 사용 | 결과는 한 번만 사용 | 결과를 여러 번 사용 |
성능 향상 방법 | 분할 자체가 성능을 높임 | 결과의 재사용이 핵심 |
🔁 Overlapping Subproblem (중복되는 부분 문제)
DP의 핵심 조건 중 하나는 중복되는 부분 문제가 존재해야 한다는 것입니다. 예를 들어, n번째 피보나치 수를 구하는 문제는 fibonacci(n-1)과 fibonacci(n-2)의 값을 구해야 하며, 이 과정에서 동일한 값(fibonacci(2), fibonacci(3) 등)을 여러 번 계산하게 됩니다.
이러한 중복을 피하기 위해, 한 번 계산한 결과를 어딘가에 저장해두고 다시 사용할 수 있어야 합니다. 이를 Memoization 또는 Caching이라고 합니다.
✨ Optimal Substructure (최적 부분 구조)
또 다른 핵심 조건은 Optimal Substructure, 즉 작은 문제의 최적해를 이용해 큰 문제의 최적해를 구할 수 있어야 한다는 것입니다. 문제를 작게 나눌 수 있고, 그 작은 문제들을 같은 방식으로 해결할 수 있다면 DP를 적용할 수 있습니다.
💡 피보나치 수열을 통해 이해하는 DP
✅ 재귀 호출 (비효율적 방식)
int fibonacci(int n){ if (n <= 1) return n; else return fibonacci(n-1) + fibonacci(n-2); }
이 방식은 간단하지만, 같은 값을 여러 번 계산하게 되어 매우 비효율적입니다.
✅ Memoization을 이용한 Top-down 방식
int memo[100] = {0,}; int fibonacci(int n){ if(n <= 1) return n; if(memo[n] > 0) return memo[n]; memo[n] = fibonacci(n-1) + fibonacci(n-2); return memo[n]; }
한 번 계산한 값을 memo 배열에 저장해두고, 이미 계산된 값은 바로 반환하여 성능을 획기적으로 개선할 수 있습니다.
🧭 DP를 푸는 두 가지 접근 방식
🔼 Top-Down 방식 (재귀 + 메모이제이션)
- 큰 문제를 작은 문제로 나눈다.
- 작은 문제의 답을 계산하고 저장한다.
- 저장된 결과를 조합해 전체 문제의 답을 구한다.
🔽 Bottom-Up 방식 (반복문 + 테이블)
- 가장 작은 문제부터 차례대로 푼다.
- 점차 문제의 크기를 키워가며 전체 문제를 해결한다.
- 일반적으로 메모리 사용을 더 잘 제어할 수 있어 효율적이다.
int fibonacci(int n){ int dp[100] = {0,}; dp[1] = 1; for(int i = 2; i <= n; i++){ dp[i] = dp[i-1] + dp[i-2]; } return dp[n]; }
🎯 정리
- 다이나믹 프로그래밍은 중복되는 문제와 최적 부분 구조가 있는 경우 사용
- 핵심은 결과 재사용을 통해 시간 복잡도를 줄이는 것
- 접근 방식은 Top-down(재귀 + 메모이제이션)과 Bottom-up(반복문 + 테이블)
'IT' 카테고리의 다른 글
가상 면접 사례로 배우는 대규모 시스템 설계 기초 4장 (2) | 2025.05.11 |
---|---|
zipkin 내용 정리 (1) | 2025.05.05 |
Jackson 직렬화 시 > 기호가 깨질 때 원인과 해결법 (0) | 2025.03.30 |
공통 쿼리 재사용을 고려한 랜덤 추출 쿼리 작성 방법 (Oracle + MyBatis) (0) | 2025.03.23 |
웹 브라우저 요청 흐름 (0) | 2025.01.06 |
댓글
이 글 공유하기
다른 글
-
가상 면접 사례로 배우는 대규모 시스템 설계 기초 4장
가상 면접 사례로 배우는 대규모 시스템 설계 기초 4장
2025.05.11 -
zipkin 내용 정리
zipkin 내용 정리
2025.05.05 -
Jackson 직렬화 시 > 기호가 깨질 때 원인과 해결법
Jackson 직렬화 시 > 기호가 깨질 때 원인과 해결법
2025.03.30 -
공통 쿼리 재사용을 고려한 랜덤 추출 쿼리 작성 방법 (Oracle + MyBatis)
공통 쿼리 재사용을 고려한 랜덤 추출 쿼리 작성 방법 (Oracle + MyBatis)
2025.03.23
댓글을 사용할 수 없습니다.