어떤 문제를 푸는가
문제를 크기가 작은 같은 형태의 부분 문제로 쪼개고, 각각을 재귀로 풀어,
그 답들을 합쳐 전체 답 을 만드는 설계 패러다임입니다. 병합 정렬, 거듭제곱
가속, 역전 카운팅, 가장 가까운 두 점 등 폭넓게 쓰입니다.
세 단계로 요약됩니다.
- 분할(Divide) — 입력을 부분 문제로 나눈다.
- 정복(Conquer) — 각 부분 문제를 재귀로 푼다 (충분히 작으면 직접).
- 결합(Combine) — 부분해를 합쳐 전체해를 만든다.
복잡도 분석 — 점화식과 마스터 정리
분할 정복의 시간은 보통
$$ T(N) = a\,T(N/b) + f(N) $$
로 표현됩니다. \(a\)는 부분 문제 수, \(b\)는 크기 축소 비율, \(f(N)\)은 결합 비용.
마스터 정리로 자주 나오는 결과:
| 점화식 | 결과 | 예 |
|---|---|---|
| \(T(N) = 2T(N/2) + O(N)\) | \(O(N \log N)\) | 병합 정렬 |
| \(T(N) = 2T(N/2) + O(1)\) | \(O(N)\) | 트리 순회류 |
| \(T(N) = T(N/2) + O(1)\) | \(O(\log N)\) | 이분 탐색 |
결합 비용 \(f(N)\)이 전체 복잡도를 좌우한다는 점이 분석의 핵심입니다.
예 1 — 빠른 거듭제곱
\(a^n\)을 \(n\)번 곱하지 않고 지수를 절반으로 줄여 계산합니다.
$$ a^n = \begin{cases} (a^{n/2})^2 & n \text{ 짝수} \\ a \cdot (a^{(n-1)/2})^2 & n \text{ 홀수} \end{cases} $$
지수가 매번 반으로 줄어 \(O(\log n)\). 모듈러 거듭제곱, 행렬 거듭제곱의 토대입니다.
예 2 — 역전 카운팅
병합 정렬을 하면서, 왼쪽 절반의 원소가 오른쪽 절반의 원소보다 클 때마다
"역전 쌍"을 셉니다. 병합 단계에서 한 번에 묶음으로 셀 수 있어 전체 \(O(N \log N)\)
에 모든 역전(앞이 뒤보다 큰 쌍)의 수를 구합니다. 단순 \(O(N^2)\)를 대체합니다.
왜 효율적인가
부분 문제를 독립적으로 풀어 중복 계산을 피하고, 결합 비용이 작을수록
재귀 트리의 각 레벨 비용이 작아집니다. 레벨 수는 \(\log_b N\)이므로, 레벨당
비용이 균형을 이루면 전체가 \(O(N \log N)\) 같은 효율로 떨어집니다.
DP와의 차이
DP도 부분 문제로 나누지만, 겹치는 부분 문제를 저장(메모이제이션) 합니다.
분할 정복은 보통 부분 문제가 겹치지 않을 때(서로 다른 구간) 적합합니다.
겹치면 DP, 안 겹치면 순수 분할 정복으로 보는 감각을 기르세요. 다음 강의에서
구현 예제를 봅니다.