◀ THE GRIND — 1-D DYNAMIC PROGRAMMING

Perfect Squares

MEDIUM✓ CHIP-TIMEDLC #279 — FULL STATEMENT ↗

The drill: Find the smallest count of square numbers (1, 4, 9, 16, …) that add up to a given n — same number can be reused as many times as needed.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

A positive integer n arrives, and the job is to express it as a sum of perfect squares — 1, 4, 9, 16, and so on — using as few squares as possible, with any square reusable as many times as needed.

Only the count of squares used matters for the answer, not which squares were chosen or in what order they're listed. Every n has at least one valid decomposition, since 1 is itself a perfect square and can always be summed n times if nothing shorter works.

The output required is that smallest count of perfect squares summing exactly to n — a single integer, with no need to report which squares were actually used.

EX 01
n = 1
1
MINIMUM SIZE, ITSELF A SQUARE
EX 02
n = 3
3
1 + 1 + 1, NO BETTER SPLIT EXISTS
EX 03
n = 4
1
A PERFECT SQUARE
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

Every amount i can be reached by landing a final square j² on top of some smaller amount i − j². What's the best way to combine the smaller amount's answer with that last jump?

HINT 2 THE STRUCTURE

dp[i] = 1 + the smallest dp[i − j²] over every square j² ≤ i, with dp[0] = 0. That's a clean bottom-up table, but it still costs a pass over every square for every amount.

HINT 3 ONE STEP FROM THE ANSWER

There's a number-theory shortcut: every n needs at most 4 squares (Lagrange). Check n itself for being a square (1), then check every j² for n − j² also being a square (2), then test Legendre's 4^a·(8b+7) form for the 4 case — anything left over is 3.

COACH'S BOARD — THE PATTERN, STEP BY STEP
THE LAGRANGE CHECKPATTERN · LAGRANGE FOUR-SQUARE CHECKn = 11
0
1
4
9
VERDICT SO FAR
— empty —
STEP 1

n = 11. First check: is 11 itself a perfect square? 3² = 9 and 4² = 16 — neither hits 11, so no.

STEP 1 / 8 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/perfect-squares.pyRACE PACE
LANG ▸
PACE ▸
class Solution:
    def numSquares(self, n: int) -> int:
        def is_square(x: int) -> bool:
            r = math.isqrt(x)
            return r * r == x

        if is_square(n):
            return 1

        # Legendre's three-square theorem: n needs all 4 squares exactly when
        # n = 4^a * (8b + 7).
        m = n
        while m % 4 == 0:
            m //= 4
        if m % 8 == 7:
            return 4

        # otherwise n is either a sum of two squares, or of three
        i = 1
        while i * i <= n:
            if is_square(n - i * i):
                return 2
            i += 1
        return 3
TIME O(√N)SPACE O(1)PYTHON · RACE PACE · 24 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED