Applied Coding › Guides › Backtracking

Choose, explore, undo — combination sum

A machine wants exactly $7. You have as many $2, $3, $6 and $7 coins as you like. Finding one way to pay is easy; finding every way, without counting the same coins twice, is where backtracking earns its name.

Pattern: Backtracking · Language: Python · Reading time ≈ 15 min · Video ≈ 8 min
The video's thumbnail: the narrator beside the coin machine that wants exactly seven dollars

Watch the video version

Eight minutes: the coin machine, the tree of choices on the floor, the walk back, and the code built line by line from what he did. The written version below keeps the whole program in one place and lets you run it with your own coins.

Watch on YouTube

1 · The problemA machine that wants exactly $7

An arcade machine has one rule: the prize is yours if you pay exactly seven dollars. No more, no less — it gives no change. You have four kinds of coins, worth $2, $3, $6 and $7, and as many of each as you want.

The narrator beside a blue arcade machine whose sign reads $7 EXACTLY, NO CHANGE; four coins, $2, $3, $6 and $7, float over his head, each marked with an infinity sign
Four kinds of coins, each one unlimited. The counter shows $0.

How hard could it be? Put coins in until the counter says seven.

2 · The obvious ideaThe first try, and the first undo

Start with a $2 coin. Then another: four. Another: six. Only one dollar is missing, and the next coin he reaches for is a $3. Six plus three is nine. Too much — and the machine does not give change, so this path is dead.

The counter on the machine shows $6 in red with TOO MUCH under it; the narrator stands beside the slot
Three $2 coins make six. Any coin added now passes seven.

He does not empty the machine and start again. He takes back the last coin — just that one — and tries something else from there. This time he stops at two plus two and tries a $3: four plus three is exactly seven.

The machine's counter reads $7 in green, its prize window open and glowing; the narrator holds up a star, and a card on the left reads [2, 2, 3]
$2 + $2 + $3. The first answer goes on a card: [2, 2, 3].

3 · The real questionOne answer isn't enough

Then he notices another way to win: a single $7 coin. And that changes the question. Finding one way to make seven was never the challenge. The challenge is finding every way.

The narrator in profile drops a single coin into the machine's slot; the counter reads $7; the card [2, 2, 3] hangs on the wall to the left
One $7 coin is a second answer. How many more are there, and how do you know you found them all?

"Every way" means you cannot stop at the first success, and you cannot trust luck to stumble on the rest. You need a way of trying things that is guaranteed to visit every possibility exactly once.

4 · The trapThe same answer, twice

Here is the second problem, and it is sneakier. Pay $2, then $3, then $2. That makes seven too. Is it a new answer?

Three cards beside the machine: [2, 3, 2] in red marked = SAME, and [7]; the narrator looks puzzled, a spiral in his thought bubble
[2, 3, 2] is the same handful of coins as [2, 2, 3], picked in a different order.

No. It is the same combination as two, two, three — the same coins in your hand — picked in a different order. The machine does not care about order, and neither does the question. So now there are two problems at once:

  1. Find every way

    Explore all the possibilities, missing none.

  2. No repeats

    Never explore the same combination again in a different order.

The problem as cards: candidates 2 3 6 7 with an infinity chip, TARGET = 7, and two goals: 1 FIND EVERY WAY, 2 NO REPEATS
The programming problem, stated without the machine.

Stated without the story: given a list of distinct positive numbers, the candidates, and a target, list every combination of candidates that adds up to the target. A candidate may be used any number of times. Two combinations that differ only in order count once. For candidates [2, 3, 6, 7] and target 7, the answer is [[2, 2, 3], [7]].

The question is how to make a computer explore all of that without losing itself.

5 · The structureEvery choice is a branch

Choose $2. From there you can choose $2 again, or $3, or $6, or $7. From each of those you have four choices again. Every choice creates another possible path, and every path offers more choices. Drawn out, the possibilities are a tree: the root is "nothing paid yet", each branch is a coin, and each point in the tree is the list of coins on the way down to it.

A tree of choices over a row of stones on the floor: from the root, branches 2, 3, 6 and 7; from each of those, branches again; the red ones pass seven
The stones on the floor are his path; the tree above them is the map of every path. Red branches pass $7.

That tree grows quickly. Try everything blindly — any coin after any coin, stopping only when you reach or pass the target — and for $7 the tree already has 37 points to visit. If the machine wanted $40, it would have 6,757,745.

A card over the floor reads TARGET 7 → 37 PATHS and, in red, TARGET 40 → 6,757,745 PATHS; the narrator, overwhelmed, points at it
Every partial path counts, because every one of them is a place you would have to stand and decide.

So the job is not "try everything". It is: walk this tree in a disciplined order, so that nothing is missed, nothing is visited twice, and branches that cannot work are left as early as possible.

6 · The moveUndo one step, not everything

Follow one path on the floor, a stone per coin. Two. Two. Two: six dollars paid, one left. Another $2 would make eight — past the target. And $3, $6 and $7 are even bigger, so none of them can work here either.

The narrator on the third stone of 2s, a red bar beside him marked TOO HIGH over a red fourth stone, the sum 6 + 2 = 8 on the left, and the coins $3, $6, $7 under EVEN BIGGER
If the smallest coin is too big, every coin is too big. This stone is a dead end.

Now the important part. He does not throw everything away and walk back to the start. He undoes the last decision only — one step back — and he is at two, two again, with four dollars paid and the next choice untried. From there, $3 makes exactly seven.

The narrator on a green stone marked 3 after two stones of 2; the sum 2 + 2 + 3 = 7 in green; the small tree over his head lights the path 2, 2, 3
One step back, one new choice: 2 + 2 + 3 = 7.

Everything before the bad step was still useful. The first two coins did not cause the problem, so they stay.

Two cards: START OVER with a red cross and a single stone, ONE STEP BACK with a green tick and the stones 2, 2 kept
Start over throws away every good choice with the bad one. One step back keeps them.

7 · The nameThis is backtracking

He is not guessing at random. He is exploring a tree of decisions, with three moves:

  1. Choose

    Pick a coin and add it to the path.

  2. Explore

    Go on from there: everything that choice can lead to.

  3. Undo

    When that is finished — success or dead end — take the coin back and try the next one.

That is backtracking: build a solution one choice at a time, explore it, and when the path fails, go back and try another choice. It doesn't mean starting over every time something fails — that is the whole point. You keep the choices that are still useful and only undo the one you need to change.

The key idea

Choose. Explore. Undo. The undo is not a cleanup step after a failure. It runs after every exploration, successful or not, because it is what makes the next choice possible.

If you have read the Sudoku solver, this is the same loop with coins instead of digits: the digit lifted off the board there is the coin taken back here.

8 · The second ruleThe gate: never go back to an earlier coin

Choose, explore, undo finds every way. It also finds [2, 3, 2] and [3, 2, 2] and [2, 2, 3] — the same combination three times. Remember why: after choosing $3, he allowed himself to go backward to $2.

So add one rule. Put the coins in a fixed order — 2, 3, 6, 7 — and once you have moved forward to a coin, you never go back to an earlier one. Like a one-way gate.

The narrator stands on the pad marked 3 and bumps into a red and white barrier that blocks the way back to the pad marked 2; pads 6 and 7 lie ahead
After a $3, the way back to $2 is shut. [2, 3, 2] can never be built.

The rule only forbids going backward. Staying is allowed: after choosing $2 you can choose $2 again, because you are not moving past it. That is how a coin is used more than once.

The narrator in front of the four pads 2, 3, 6, 7; above him a looping arrow and the sequence 2 → 2 → 2 → 3 → 6 → 7
Stay on the same coin as often as you like, or move forward. Never back.

Why does this kill the duplicates without losing any answer? Because every combination has exactly one way of being written with its coins in non-decreasing order: [2, 2, 3], never [2, 3, 2]. The gate makes that the only order the search can produce, so each combination is built once.

9 · The codeThe code, one action at a time

Nothing magical happens in the code. It copies what he did on the floor, one action per line. First, the two things he carries: the answers found so far, and the path — the coins in his backpack right now.

class Solution:    def combinationSum(self, candidates, target):        result = []        path = []

The function that explores

One function, backtrack, does the walking. It needs to know two things: where it may start choosing from (the gate), and how much of the target is still left.

        def backtrack(start, remaining):

When the path is an answer

If nothing is left to pay, the path adds up to the target. Save it and stop exploring this branch — any coin added now would pass the target.

        def backtrack(start, remaining):            if remaining == 0:                result.append(path[:])                return
The narrator on his stone beside the code panel; the lines if remaining == 0, result.append(path[:]) and return are lit; the state strip reads remaining 5, path [2], result [[2, 2, 3]]
The panel follows him on the stones: the lit line, and under it what is left, the path and the answers.
Why path[:] and not path

path[:] saves a copy. The search is about to keep changing path — taking coins back, adding others. Save the list itself and your answer changes with it: by the end of the search every saved answer would be the same empty list.

Try every coin you are allowed to choose

Otherwise, go through the candidates — but only from start onward. That is the gate in code: the loop never looks at a coin before start, so it can never go backward.

            for i in range(start, len(candidates)):                if candidates[i] > remaining:                    break

Stop when the coin is too big

If the current coin is already bigger than what is left, every coin after it is bigger too — if the coins are in order. So the very first thing the function does is sort them, and then a too-big coin can end the loop with break instead of checking the rest.

        candidates.sort()
            for i in range(start, len(candidates)):                if candidates[i] > remaining:                    break
The narrator on the stone 2 beside the code panel with if candidates[i] > remaining lit; the state strip shows remaining 5, path [2] and a red chip 6 > 5; the stone marked 6 ahead of him is red
With $5 left, the $6 coin is too big — and so is the $7 after it. One break skips both.

Choose

Make the choice by adding the coin to the path. That is the coin picked up and dropped in the backpack.

                path.append(candidates[i])

Explore

Then call backtrack again: one level deeper into the tree, with the coin just chosen subtracted from what is left.

                path.append(candidates[i])                 backtrack(                    i,                    remaining - candidates[i]                )

Look at the first argument. It is i, not i + 1. The next call may start choosing from the same coin — that is "stay on the same pad". Pass i + 1 and the search would move past the $2 the moment it chose one, and [2, 2, 3] could never be built.

The panel with the argument i lit; under it the candidate chips with the 2 crossed out and the 3 lit: what i + 1 would allow
With i + 1: the 2 is crossed out, the next call could only start at 3.
The same panel; now the candidate chip 2 is lit as the start of the next call, and the narrator raises a hand
With i: the 2 stays available for the next decision.

Undo

And the most important line. When the deeper exploration is finished — whether it found answers or hit a dead end — remove the last choice.

                path.append(candidates[i])                 backtrack(                    i,                    remaining - candidates[i]                )                 path.pop()

path.pop() is him walking backward one stone. Without it, the coin would still be in the backpack when the loop tries the next coin, and the path would only ever grow.

The narrator stepping backward off a stone while the line path.pop() is lit on the panel; the strip reads remaining 3, path [2, 2]
path.pop() lit on the frame he steps back.

Start it, and return the answers

The first call starts at the first coin with the whole target still to pay.

        backtrack(0, target)         return result

The whole thing

class Solution:    def combinationSum(self, candidates, target):        result = []        path = []         candidates.sort()         def backtrack(start, remaining):            if remaining == 0:                result.append(path[:])                return             for i in range(start, len(candidates)):                if candidates[i] > remaining:                    break                 path.append(candidates[i])                 backtrack(                    i,                    remaining - candidates[i]                )                 path.pop()         backtrack(0, target)         return result

Three lit lines, three moves: line 17 chooses, lines 19–22 explore, line 24 undoes. The loop around them tries the next choice.

The whole program on a poster in two halves beside the narrator, the line candidates.sort() highlighted
The complete solution, as it appears at the end of the code part of the video.

If you remember nothing else, remember the physical story:

In the storyIn the code
The coins in my backpackpath
The cards on the wallresult
Exactly seven: an answerif remaining == 0: result.append(path[:])
The one-way gatefor i in range(start, …)
Too high, and every bigger coin tooif candidates[i] > remaining: break
I pick up a coinpath.append(candidates[i])
I walk deeper, on the same pad if I likebacktrack(i, remaining - candidates[i])
I walk backwardpath.pop()
I try the next branchthe next turn of the for loop

10 · The real runEvery move the program makes

Here is the program above, run on [2, 3, 6, 7] and 7, every event in order. "Choose" is line 17, "undo" is line 24, "too big" is the break on line 15.

#What happensPath after itLeft
The narrator back at START after the live run; the monitor's strip reads remaining 7, path [], result [[2, 2, 3], [7]]
After the last event: the path is empty again, two answers on the wall. Every choice undone.

Count them: 9 choices, 9 undos, 10 calls, and two answers. Every coin that went into the backpack came back out — that is what lets the next branch start clean.

Honesty note

At the machine, the story tries a $3 after two, four, six and gets nine. The program never tries that: with $1 left, the very first coin it looks at, the $2, is already too big, and because the coins are sorted the break ends the loop there (event 4). The floor scenes of the video show the program's version — six plus two is eight, and $3, $6, $7 are "even bigger". The machine scene is the idea; the table is the program.

11 · The costWhat it costs

The two rules are not only about correctness. Each one cuts the tree. Count the calls to backtrack — the points of the tree the program actually visits:

SearchTarget 7Target 40Answers for 40
Blind: any coin after any coin376,757,745748,874 (with every order)
With the gate (start)281,48477
With the gate, sorted, with break1097377

The gate is the big one. It turns 748,874 ordered sequences into the 77 combinations that were actually asked for, and the tree shrinks with them — from almost seven million calls to under fifteen hundred. The sort and the break then stop every branch at the first coin that is too big instead of trying each bigger coin and failing.

Target 40 · blind6,757,745calls
Target 40 · gate + break973calls

Time: exponential in the worst case — the number of combinations itself can grow exponentially with the target, and the program has to build each one. A common bound is O(NT/M) for N candidates, target T and smallest candidate M: the tree is at most T/M levels deep with at most N branches per point. Space: O(T/M) for the path and the call stack — the deepest path is all smallest coins — plus the answers themselves.

That is the usual shape of backtracking: you cannot avoid walking the tree, so the craft is in making the tree smaller — rules that refuse a branch as early as possible.

12 · Try itYour own coins, your own target

Run the program step by step

The Python above, translated to run in your browser. Change the coins and the target, switch the two rules off and on, and watch what each one does to the answers and to the number of calls.

Backpack (path)
empty
What just happened
Press Step.
Answers (result)
left 7choices 0undos 0calls 0answers 0

Things to try: switch the gate off and watch [2, 3, 2] and [3, 2, 2] appear in red. Switch the break off and watch the program walk into $8 and $9 before turning back. Then put both back and set the target to 40.

13 · The bigger ideaWhat if order mattered?

Backtracking shows up wherever a problem asks you to explore a huge number of choices: a Sudoku, placing queens on a chessboard, finding a way through a maze, listing every order of a few things. The structure is the same each time: choose something, explore what happens, and if the path can't work, undo the choice and try another.

The tree of choices over the narrator, its dead branches marked with red crosses; under it the words SUDOKU, N-QUEENS, MAZES, PERMUTATIONS, COMBINATION SUM
One tree, many problems. What changes is what a choice is, and what rules a branch out.

So try this before you go: in this problem, [2, 3, 2] is the same answer as [2, 2, 3]. What if order suddenly mattered? Then [2, 2, 3], [2, 3, 2] and [3, 2, 2] are three different answers, and two answers become four.

WHAT IF ORDER MATTERS? in red over four cards: [2, 2, 3], [7], [2, 3, 2], [3, 2, 2]; under them 2 → 4 ANSWERS and NEXT: PERMUTATIONS
When every order counts, the answers are permutations — and the tree changes completely.

Which line of the program would you change? (Hint: the gate. With the gate off, the lab above already counts the four.)

Before you write any code

Don't start by memorizing the program. Draw the decision tree first, and answer three questions: What are the choices? When does a path fail? What decision do you undo? If you can explain those three actions, the code is much easier to write.

14 · PracticeFour problems, same shape

For each one, write down the three answers — the choices, the failure, the undo — and the rule that stops repeats, before touching the keyboard.

  • Warm-upSubsets

    List every subset of a few distinct numbers. Every point of the tree is an answer, not only the leaves. Where does the "save a copy" line go now?

  • PracticeCombination sum, from scratch

    Close this page and write it yourself. Then switch the gate off in your own code and check that you get four answers for 7 — and 6,757,745 calls for 40 if you also drop the sort and the break.

  • VariationEach coin only once

    The pile now has a fixed set of coins, some of them equal (say 1, 1, 2, 5, 6, 7, 10), and each can be used once. Two changes: what is the next call's start, and how do you stop the two 1s from producing the same combination twice?

  • ChallengePermutations

    Every order of a few distinct numbers. The gate is gone — order matters now — so what stops you from using the same number twice in one path?

The word BACKTRACKING beside a Sudoku board with its finished top row

Same pattern, another board — the Sudoku solver →

Choices are digits, a dead end is a square where nothing fits, and the undo is a digit lifted off the board. Then part 2 shows how the order of the choices takes 4,208 placements down to 51.

Choose. Explore. Undo. Then try the next one.