topic★★★★★난이도 · 약 20분
재귀 · 분할정복 — 자기 자신을 부르는 함수
탈출 조건 + 자기 호출. 트리 순회·머지 정렬·DP의 뼈대. 스택 오버플로 주의.
#재귀#분할정복#머지정렬#기저사례
왜 배우는가
JSON 구조 순회·디렉토리 탐색·DOM 탐색 — 전부 재귀가 자연스럽다. 탈출 조건이 빠지면 스택 오버플로(ch14-3). AI가 만든 재귀 코드가 맞는지 보는 눈.
재귀(Recursion)의 뼈대는 두 줄. ① 기저 사례(base case) — 멈추는 조건. ② 재귀 호출 — 문제를 작은 자신으로 축소. 기저가 없거나 잘못되면 무한 반복 → 스택 오버플로.
javascript
// 팩토리얼 — 가장 쉬운 예
function fact(n) {
if (n <= 1) return 1; // ① 기저
return n * fact(n - 1); // ② 재귀
}
// 트리·JSON 순회 (실전)
function walk(node, fn) {
fn(node);
for (const child of node.children ?? []) walk(child, fn);
}
walk(root, n => console.log(n.name));
// 파일 시스템 순회
async function listAll(dir) {
const items = await fs.readdir(dir, { withFileTypes: true });
for (const item of items) {
const full = path.join(dir, item.name);
if (item.isDirectory()) await listAll(full); // 재귀
else console.log(full);
}
}재귀가 어울리는 문제: 트리·JSON·디렉토리·수식·그래프 DFS. 반복문이 더 어울리는 문제: 평평한 배열·누적합.
분할정복(Divide & Conquer)은 재귀의 고급형. ① 나누고(divide) ② 각각 풀고(conquer) ③ 합친다(combine). 머지 정렬·퀵 정렬·이진 탐색의 공통 뼈대. Big O 분석이 마스터 정리(master theorem)로 체계화.
javascript
// 머지 정렬 — 분할정복 교과서
function mergeSort(arr) {
if (arr.length <= 1) return arr;
const mid = arr.length >> 1;
const left = mergeSort(arr.slice(0, mid)); // 나누기
const right = mergeSort(arr.slice(mid));
return merge(left, right); // 합치기
}
function merge(a, b) {
const out = [];
let i = 0, j = 0;
while (i < a.length && j < b.length) {
out.push(a[i] <= b[j] ? a[i++] : b[j++]);
}
return [...out, ...a.slice(i), ...b.slice(j)];
}
// O(n log n) — log n개 단계 × 각 단계 O(n) 합치기머지·퀵 정렬, FFT, 크고 작은 배열 비교 — 분할정복 패턴 자체가 성능 돌파구.
재귀 최적화 2종. ① 꼬리 재귀(tail call) — 마지막에 자기 호출만 하면 컴파일러가 반복문으로 치환 가능(JS는 엔진별 편차). ② 메모이제이션 — 같은 인자 재호출 결과를 캐시(ch18-4 DP). 재귀가 느리면 이 둘부터 본다.
실기 드릴 2문항
edit실기 드릴 · 단답형
재귀 함수에서 호출을 멈추는 조건을 가리키는 용어는?
check_circle실기 드릴 · OX
머지 정렬의 시간복잡도는 O(n²)이다.