DP 타뷸레이션은 작은 답부터 어떤 순서로 테이블을 채우나요?
타뷸레이션은 필요한 작은 답을 먼저 채워 큰 답으로 올라가는 방식입니다. 계산하려는 칸보다 먼저 필요한 칸이 완성돼 있어야 합니다.
적용 조건·범위: 분석 조건: 정수 0≤n≤78. 최종 값 하나만 요구할 때 두 변수 최적화가 가능합니다.
본문 근거: Competitive Programmer’s Handbook · MDN — Number.MAX_SAFE_INTEGER
읽기 전에 알아두면 좋아요
아래 개념이 익숙하면 본문을 바로 읽으세요. 낯선 개념만 링크에서 복습하면 됩니다.
- DP 메모이제이션: 피보나치의 중복 호출 줄이기동적 계획법은 같은 작은 문제의 결과를 저장해 다시 계산하는 일을 줄이는 방법입니다.
- JavaScript 배열: 인덱스 조회와 삽입·삭제 비용배열은 여러 값을 순서대로 담습니다. 인덱스로 값을 읽고 반복문으로 하나씩 살펴봅니다.
개념과 예제는 실행하지 않아도 읽을 수 있습니다. 내 컴퓨터·터미널에서 직접 실행하는 과정은 선택 실습입니다.
과정 위치와 선택 복습 안내
과정 위치: 동적 계획법의 두 계산 순서 · 알고리즘 개념
과정 위치는 이 글이 속한 묶음입니다. 이 단계의 모든 개념을 먼저 읽을 필요는 없습니다. 위에 연결한 개념 중 낯선 내용만 복습하세요. 문제의 조건·상태·갱신 순서는 익숙한 언어로 설명하면 됩니다.
JavaScript로 문법·실행 복습하기 (선택)
개념 글의 코드는 JavaScript 예시입니다. 문제 화면에서는 JavaScript·Python·Java·C++·C# 중 익숙한 언어의 함수를 작성하세요. 본문의 Node.js 입출력 예시는 로컬 실행을 위한 별도 안내입니다.

타뷸레이션은 필요한 작은 답을 먼저 채워 큰 답으로 올라가는 방식입니다. 계산하려는 칸보다 먼저 필요한 칸이 완성돼 있어야 합니다.
선수 지식: 배열 인덱스·반복문과 F(n)=F(n−1)+F(n−2)의 의미를 알아야 합니다.
- 하위 상태가 먼저 완성되는 계산 순서를 정합니다.
- 테이블을 두 변수로 줄일 때의 갱신 순서를 설명합니다.
앞의 두 칸이 채워진 뒤 다음 칸을 씁니다
F(0)=0과 F(1)=1을 배열에 넣고 i=2부터 시작합니다. i번째 값을 채울 때 참조하는 것은 i−1과 i−2뿐입니다. 인덱스가 증가하는 순서라면 두 칸이 이미 완성돼 있다는 사실을 매번 보장할 수 있습니다. for문의 방향은 단순한 취향이 아니라 상태 사이의 의존 관계에서 나옵니다.

| 채울 위치 | 이미 구한 값 | 새 값 |
|---|---|---|
| 2 | F(0)=0, F(1)=1 | 1 |
| 3 | F(1)=1, F(2)=1 | 2 |
| 4 | F(2)=1, F(3)=2 | 3 |
| 5 | F(3)=2, F(4)=3 | 5 |
반복 직전까지 values[0]부터 values[i−1]이 정확하다는 약속을 유지합니다. 이를 바탕으로 두 값을 더하면 i번째도 정확합니다. 0과 1에서는 반복을 시작하지 않고 바로 반환합니다.
뒤에서 다시 읽지 않는 칸은 보관하지 않아도 됩니다
마지막 답 하나만 필요하다면 오래된 칸을 전부 남길 이유가 없습니다. i번째 값을 계산하기 직전 previous는 F(i−2), current는 F(i−1)입니다. next=previous+current를 먼저 계산합니다. 그다음 previous=current, current=next로 옮기면 같은 약속이 한 단계 뒤로 이동합니다. 첫 변수를 덮어쓴 뒤 그 값으로 두 번째를 계산하면 원래 더해야 할 값 하나를 잃어버립니다.

이 방식은 언제나 테이블을 대체하지는 않습니다. 모든 F(0)~F(n)을 보여 주거나 중간 상태를 이용해 선택 경로를 복원해야 한다면 저장한 칸이 다시 필요합니다. 공간을 줄이는 판단은 입력 크기뿐 아니라 최종적으로 어떤 결과를 요구하는지에서 시작합니다.
메모이제이션과 타뷸레이션의 답은 같아야 합니다
두 방식은 같은 점화식을 계산하므로 같은 입력에서 결과가 일치해야 합니다. 메모이제이션은 요청된 상태부터 내려가고, 타뷸레이션은 의존 순서에 맞게 올라옵니다. 실제 문제가 모든 상태를 요구하지 않는다면 요청한 상태만 푸는 방법이 유리할 수 있습니다. 반대로 이 피보나치처럼 거의 모든 작은 상태를 쓰면 순서가 단순한 반복문을 선택하기 쉽습니다.

테이블 방식도 입력과 정수 범위를 무시할 수는 없습니다. 두 구현 모두 0~78만 허용하며 79, 음수, 소수는 거절합니다. 재귀가 없어졌다는 이유로 Number가 무한한 정수를 정확히 저장한다고 생각하지 않아야 합니다.
전체 코드와 직접 실행
개념을 읽었다면 아래 예제를 직접 실행하며 상태 변화를 확인할 수 있습니다.
전체 JavaScript 코드와 실행 방법 펼치기
별도 패키지는 필요하지 않습니다. Node.js가 처음이라면 브라우저와 Node.js 시작 안내부터 확인하세요.
dp-tabulation.mjs 파일을 만들고 아래 전체 코드를 저장합니다.
function checkFibonacciInput(n) {
if (!Number.isInteger(n) || n < 0 || n > 78) {
throw new RangeError('n은 0 이상 78 이하의 정수여야 합니다.');
}
}
function fibonacciTable(n) {
checkFibonacciInput(n);
if (n < 2) return n;
const values = [0, 1];
for (let i = 2; i <= n; i++) values[i] = values[i - 1] + values[i - 2];
return values[n];
}
function fibonacciRolling(n) {
checkFibonacciInput(n);
if (n < 2) return n;
let previous = 0;
let current = 1;
for (let i = 2; i <= n; i++) {
const next = previous + current;
previous = current;
current = next;
}
return current;
}
console.log(fibonacciTable(10));
console.log(fibonacciRolling(10));
파일이 있는 폴더의 터미널에서 실행합니다.
node dp-tabulation.mjs
기대 출력
55
55
비용과 적용 범위
시간: 두 방식 모두 O(n)번 덧셈입니다.

공간: 테이블은 O(n), 두 변수 방식은 O(1) 추가 공간입니다.
분석 조건: 정수 0≤n≤78. 최종 값 하나만 요구할 때 두 변수 최적화가 가능합니다.
직접 확인해 보기
F(6)=8까지 계산한 상태에서 previous=5, current=8입니다. 다음 값을 한 번 계산하면 무엇이 되나요?

답과 이유 확인
먼저 next=13을 구한 뒤 previous=8, current=13으로 바꿉니다. 이전 값을 지우기 전에 합을 계산해야 합니다.
함께 읽을 글
- 기초 구현 패턴 — 반복에서 어떤 값을 보관하고 갱신하는지 먼저 익힙니다.
- JavaScript 배열의 연산 비용 — 테이블의 인덱스와 추가 공간 비용을 이해합니다.
참고 자료
- Competitive Programmer’s Handbook — 동적 계획법의 상태·전이, 부분집합과 순회 최적화의 일반 원리를 대조합니다. 예제와 설명은 이 원고의 독립 구현입니다.
- MDN — Number.MAX_SAFE_INTEGER — Number 정수 정밀도의 한계와 이 예제의 피보나치 상한을 구분합니다.
이 글이 도움이 되었나요?
이어서 공부하기
체크포인트: 예제의 상태 변화를 손으로 추적하고 아래 문제에 적용하세요. 값이 없는 경우와 원소 하나인 경우도 설명해 보세요. 같은 부분 문제를 다시 계산하는 지점과 저장한 값을 재사용하는 지점을 구분하세요.
다음 추천 · 자료구조 개념: 트리 자료구조 차이: 이진 트리 BST MST 구분하기
권장 순서는 학습 가이드와 같습니다. 다른 순서는 접힌 참고 목록에서 확인할 수 있습니다. 읽음 표시는 숙달이나 채점 결과가 아닙니다.
원래 과정 목록 순서 (선택)
읽음 기록
읽음 — / 전체 30개 · 필수 0개
새 글 받아보기
RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.