📘 CodingMarble Learn

Dynamic Programming

Dynamic programming (DP) solves a big problem by solving each smaller subproblem only once and saving the answer. It works when subproblems overlap and the best answer is built from best answers of smaller parts (optimal substructure). Top-down DP is memoization; bottom-up DP fills a table. DP often turns exponential time into polynomial time.

🎬 Step-by-step story

  1. Plain recursion for fib(5): each box calls two smaller boxes. The tree grows fast: 15 calls for a small number.
  2. Look at the colours: fib(3) is worked out twice and fib(2) three times. The same small question repeats. These are overlapping subproblems.
  3. Memoization: the first time we solve a box, we write the answer in a table. Next time we just read it. The repeated branches vanish: 15 calls drop to 9.
  4. Bottom-up (tabulation): start from the smallest cells and fill the table left to right. Each cell is the sum of the two cells before it. No recursion at all.
  5. Greedy grabs the biggest coin first: for 6 with coins {1, 3, 4} it takes 4 + 1 + 1 = 3 coins. DP checks every smaller amount and finds 3 + 3 = 2 coins.
  6. Your turn: choose n and press Fill. Compare the number of plain-recursion calls with the DP steps.

Tip: drag the 3D scene to turn it. Use two fingers to zoom.

🤔 Common doubts, cleared

Why is plain recursion so slow for Fibonacci?

Each call makes two more calls, so the tree doubles at almost every level, even though most boxes are repeats.

How do I know a problem has overlapping subproblems?

Draw the call tree for a small input. If the same box (same inputs) appears more than once, they overlap.

Where is the memo stored?

In a dictionary or array outside the recursive calls, so every call can read it.

Is tabulation the same as memoization?

Same answers and same time, different order: memoization starts from the top and recurses, tabulation starts from the base cases and loops upward.

If greedy is faster, why not always use it?

Greedy never reconsiders a choice, so it can lock in a wrong one. DP checks every option for each amount.

How much faster is DP really?

For fib(10) plain recursion makes 177 calls, DP needs 11 steps. Try it in free play.

Why plain recursion can be slow

The Fibonacci rule is fib(n) = fib(n − 1) + fib(n − 2), with fib(0) = 0 and fib(1) = 1. Written as plain recursion, each call makes two more calls. The number of calls grows roughly like 1.6n: fib(30) needs over a million calls. This is exponential time.

The waste comes from solving the same subproblem again and again.

The two conditions for DP

  1. Overlapping subproblems: the same smaller problem appears many times.
  2. Optimal substructure: the best answer to the big problem is built from best answers to smaller ones.

To design DP: (1) define the state (what one table cell means), (2) write the recurrence (how a cell uses smaller cells), (3) set the base cases, (4) choose the order to fill cells, (5) read the answer.

Top-down (memoization) and bottom-up (tabulation)

Memoization (top-down)

Keep recursion but remember answers in a dictionary or array.

memo = {}
def fib(n):
    if n < 2:
        return n
    if n in memo:
        return memo[n]
    memo[n] = fib(n - 1) + fib(n - 2)
    return memo[n]

Tabulation (bottom-up)

Fill an array from the smallest case upward with a loop.

def fib(n):
    F = [0] * (n + 1)
    if n > 0: F[1] = 1
    for i in range(2, n + 1):
        F[i] = F[i - 1] + F[i - 2]
    return F[n]

Both run in O(n) time instead of exponential. Tabulation uses no call stack, so it cannot overflow. The table version can even keep only the last two values: O(1) memory.

Other programming methods: greedy, backtracking, divide and conquer

Coin change by DP

def min_coins(coins, amount):
    INF = float('inf')
    best = [0] + [INF] * amount
    for a in range(1, amount + 1):
        for c in coins:
            if c <= a and best[a - c] + 1 < best[a]:
                best[a] = best[a - c] + 1
    return best[amount]

Time O(amount × number of coins).

Try it: count staircase paths

You climb a staircase taking 1 or 2 steps at a time. How many ways to reach step 6? Make a table: ways[0] = 1, ways[1] = 1, ways[i] = ways[i − 1] + ways[i − 2]. Fill it on paper (answer: 13). It is the Fibonacci pattern again. Check by running the bottom-up table in the last 3D step, then code it in Python.

Key formulas and definitions

Worked examples

1. Fill the table F[0..7] for Fibonacci.

0, 1, 1, 2, 3, 5, 8, 13. Each value is the sum of the two before it.

2. How many calls does plain recursion make for fib(5)?

Calls(0) = Calls(1) = 1. Calls(2) = 3, Calls(3) = 5, Calls(4) = 9, Calls(5) = 1 + 9 + 5 = 15.

3. With memoization, how many calls for fib(5)?

Each n from 5 down to 2 makes 2 calls the first time; total 2 × 5 − 1 = 9 calls.

4. Fewest coins for 6 with coins {1, 3, 4} by DP.

best[0..6] = 0, 1, 2, 1, 1, 2, 2. best[6] = 1 + min(best[5], best[3], best[2]) = 1 + 1 = 2 (3 + 3).

5. Staircase: 1 or 2 steps at a time, ways to reach step 5?

ways = 1, 1, 2, 3, 5, 8 for steps 0..5, so 8 ways.

6. Grid paths: moving only right or down in a 3 × 3 grid of cells (corner to corner). How many paths?

paths[i][j] = paths[i−1][j] + paths[i][j−1], first row and column = 1. Table rows: 1 1 1 / 1 2 3 / 1 3 6. Answer 6.

Common mistakes

Practice quiz

1. DP is useful when subproblems are:
2. Memoization means:
3. Time of DP Fibonacci:
4. Greedy for 6 with coins {1, 3, 4} uses:
5. Which method undoes a step when it leads to a dead end?

Practice: answer these yourself

Type or choose your answer, then press Check. Use a hint if you are stuck; the full solution appears after you answer.

Frequently asked questions

What is dynamic programming in simple words?

Breaking a problem into smaller overlapping problems, solving each once, saving the answers in a table and reusing them.

What is the difference between dynamic programming and recursion?

Recursion is a way of writing a function that calls itself. DP is a strategy that saves subproblem answers; it can be written with recursion (memoization) or loops (tabulation).

What is the difference between DP and divide and conquer?

Both split problems. In divide and conquer the parts are independent; in DP they overlap, so DP saves answers to avoid repeating work.

Where this is taught

RomaniaClasa a XI-aProgramming methods
Ukraine11 класAlgorithms
Russia11 классAlgorithms and programming

Learn first

Learn next

Related lessons

All Computer Science lessons