Free beta: 60 days of full access, no card needed.84 seats leftSign up free

We use necessary cookies to run the site (sign-in and language). If you accept, we also load Google Analytics to see which pages are used, and Google reCAPTCHA to keep spam off the contact and bug-report forms. Privacy policy

All patterns

Recursion with memoization

O(states)

Recursion that writes down every answer it computes. When the same argument comes back, the stored value is handed back.

Updated Oct 17, 2026

How does Recursion with memoization work?

Write the plain recursion first. Get it correct before trying to make it fast.

Look at what the arguments really are. If two calls share them, they share the answer.

Add a cache keyed by those arguments. A map or a plain array both work.

At the top of the function, return the cached answer if one exists. Nothing else runs.

Before returning, store the answer under its key. The next call reads it instead of recomputing.

Each distinct argument is now computed once. The tree of calls collapses into a graph.

Sources: Wikipedia: Memoization, Python docs: functools.cache

  1. fib(5) needs fib(4) and fib(3)The naive version splits into two calls.
  2. fib(4) needs fib(3) and fib(2)Now fib(3) is wanted twice over.
  3. cache = {2: 1, 3: 2}The first fib(3) is computed and stored.
  4. fib(3) is a lookupThe second fib(3) reads the cache. Its whole subtree is skipped.
  5. 15 calls become 9Without a cache, fib(50) would take billions of calls.
Fibonacci with a memo table
fib(5)
call stack
empty
memo: n → fib(n)
n=2n=3n=4n=5
memo
calls = 0cache hits = 0

Compute fib(5). Plain recursion asks for the same fib(n) many times. memo stores each answer the first time it is found.

Speed race
fib(17) by plain recursion and by the same recursion with a memo

Bars: how many times fib(i) was actually computed, i from 0 to 17. A call answered from the memo computes nothing, so its bar stays put.

One operation is one call, and an answer read from the memo counts as one. Every frame, each lane does the same number of operations, so the slow one falls behind.

Plain recursion O(2ⁿ)
0 operations
Recursion with a memo O(n)
0 operations

 

And with more numbers

Operations for n numbers, and roughly how long they take at 100 million simple operations a second. An estimate from the same count, not a measurement.

n = 20
Plain recursion21.9K · under 1 ms
Recursion with a memo39 · under 1 ms
n = 40
Plain recursion331.2M · 3.3 s
Recursion with a memo79 · under 1 ms
n = 60
Plain recursion5T · 14 h
Recursion with a memo119 · under 1 ms

The Recursion with memoization code template

function fib(n, memo = new Map()) {
    if (n <= 1) return n;
    if (memo.has(n)) return memo.get(n);
    const result = fib(n - 1, memo) + fib(n - 2, memo);
    memo.set(n, result);
    return result;
}

A worked example of Recursion with memoization

Fewest coins for an amount

You get a list of coin values and an amount. Return the fewest coins that add up to it.

If no combination works, return minus one.

Ask the same question about a smaller amount. Each coin gives one branch.

The remaining amount alone identifies a subproblem. So the cache is keyed by that amount.

function coinChange(coins, amount) {
    const cache = new Map();

    function best(left) {
        if (left === 0) return 0;
        if (left < 0) return Infinity;
        if (cache.has(left)) return cache.get(left); // computed before

        let answer = Infinity;
        for (const coin of coins) {
            answer = Math.min(answer, best(left - coin) + 1);
        }

        cache.set(left, answer); // store the failure too
        return answer;
    }

    const result = best(amount);
    return result === Infinity ? -1 : result;
}

When should you use Recursion with memoization?

Use Recursion with memoization when the problem statement says “recursive calls repeat the same arguments (overlapping subproblems)”, “plain recursion is correct but too slow / exponential blow-up” or “small number of distinct states even though the recursion tree is huge”. A solution built on it usually runs in O(states).

  • recursive calls repeat the same arguments (overlapping subproblems)
  • plain recursion is correct but too slow / exponential blow-up
  • small number of distinct states even though the recursion tree is huge
  • cache/memo the result of (i, ...) before returning
  • Fibonacci / climbing stairs / grid-path wording with a hint to cache

The signal words of every pattern sit in one table, the algorithm patterns cheat sheet.

What is Recursion with memoization confused with?

Recursion with memoization is most often confused with Recursion, Dynamic programming (1-D), Hash set / map and Backtracking.

  • Recursion: Plain recursion recomputes a repeated argument every time. The cache is the entire difference.
  • Dynamic programming (1-D): Bottom-up DP fills a table in a fixed order. This fills it on demand, from the top down.
  • Hash set / map: The cache is usually a map. This page is about deciding when to keep one.
  • Backtracking: Backtracking explores paths that all differ, so nothing repeats. A cache there stores keys never asked again.

Common mistakes with Recursion with memoization

  • A key that leaves out an argument

    Every value the answer depends on belongs in the key. A partial key returns another call's answer.

  • Caching a mutable object

    Storing a reference lets a later call change it. Store a copy or a plain value.

  • Not caching a failure

    A branch that fails is still an answer worth keeping. Otherwise dead ends get explored again.

  • Caching where nothing repeats

    If every argument is unique, the cache only costs memory. Check the overlap before adding it.

Interview problems solved with Recursion with memoization include Fibonacci, Climbing stairs, Coin change, House robber, Word break, Unique paths and Longest increasing path in a matrix.

  • Fibonacci: The shortest example of an overlapping subproblem.
  • Climbing stairs: The same shape with a different base case.
  • Coin change: Keyed by the amount still left.
  • House robber: Keyed by the index you are standing on.
  • Word break: Keyed by the start position in the string.
  • Unique paths: Keyed by the pair of coordinates.
  • Longest increasing path in a matrix: Keyed by the cell, and no visited set is needed.

What is the time and space complexity of Recursion with memoization?

The target complexity of Recursion with memoization is O(states).

Cost is the number of distinct arguments times the work per call. A cache of 1e6 keys is fine.

See where this fits in the 150-step track