← DSA Atlas
Dedicated problem page · #282

Expression Add Operators

HardBacktrackingBacktracking over operator insertion with multiplication carryDFS building expressions while tracking the last operand for precedence
Solve on LeetCode ↗
282
HardBacktrackingDFS building expressions while tracking the last operand for precedenceBacktracking over operator insertion with multiplication carry

Expression Add Operators

Given a string num of digits and an integer target, insert the binary operators +, -, and * (and choose multi-digit operands) between the digits so the resulting arithmetic expression evaluates to target. Return all such expressions. Operands may not have leading zeros.

Open official problem prompt ↗
In plain English

Produce every arithmetic string formed by grouping the digits into operands and inserting +, -, or * that evaluates to the target.

Picture it like this

Like filling the gaps between beads on a string with plus, minus, or times signs (or gluing beads into a bigger number), then checking if the whole thing computes to the target; multiplication is tricky because it reaches back and rewrites the previous addition.

Example
Input
num = "123", target = 6
Output
["1*2*3","1+2+3"]
Why
1*2*3 = 6 and 1+2+3 = 6 are the only ways to insert operators between 1, 2, 3 to reach 6.
Constraints
1 <= num.length <= 10num consists of only digits-2^31 <= target <= 2^31 - 1Operands cannot contain leading zeros
Pattern lesson

See the pattern, then code

Backtracking over operator insertion with multiplication carry
Recognition clue

Choosing where to place +, -, * among digits and needing ALL expressions hitting a target is a backtracking-over-choices problem, complicated by * needing to override the previous addition.

Backtracking

Generate every valid combination, permutation, partition, or configuration.. Carry the running value and the last operand added; for multiplication, subtract the last operand and re-add last*current so precedence is handled without re-parsing.

New words, made simpleKnow these before the algorithm
Operand
A consecutive run of digits treated as one number, e.g. '12' in '1+23'.
last operand
The value most recently combined into the total, needed to correctly apply the next multiplication.
Precedence carry
The trick cur_val - last + last*val that removes the prior term and reinserts it multiplied.
Approaches from first idea to best ideaCompare the trade-offs
ApproachHow it thinksCost
Insert operators then eval() each string

Correct but re-parses precedence repeatedly and is slow and fragile.

Generate all operator placements and evaluate each expression with a parser.

Time O(4^n * n)Space O(n)
The rule we keep true

Invariant

cur_val equals the value of the expression string built so far under normal precedence, and last equals the signed value of its final additive term.

Why this is correct

Reasoning

For + and - the new operand becomes a fresh additive term, so last is set to that signed value. For *, the previous term must bind tighter: removing last and adding last*val transforms a+b into a+(b*c), exactly matching operator precedence, so cur_val stays correct at every step.

The algorithm in three movesSay these aloud before coding
1Extend an operand num[index:end], breaking if it has a leading zero

expr='1', val=1, last=1

2At the first operand, seed the value and last with it (no operator)

'1*2': val = 1-1+1*2 = 2, last=2

3For +, add the operand and set last to +operand

'1*2*3': val = 2-2+2*3 = 6 -> record

4For -, subtract and set last to -operand

5For *, undo last then add last*operand, setting last to last*operand

Visual trace

Follow the data, one decision at a time

Input snapshotHighlighted cells are involved in this example
10
21
32
1 · Readindex=0, operand '1'
2 · AskFirst operand has no leading operator
3 · Update stateexpr='1', val=1, last=1
4 · ResultRecurse at index 1
Key takeaway

Digits 1, 2, 3 with operators being inserted in the gaps between them.

Code walkthrough

Read the solution in small chunks

Python 3

Do not memorize the whole program. Connect each group of lines to one job in the algorithm.

  1. 1
    Lines 7-10Terminal check

    Once all digits are consumed, keep the expression only if it evaluates to target.

  2. 2
    Lines 11-15Form the next operand

    Extend the substring and break on a multi-digit operand starting with 0 to forbid leading zeros.

  3. 3
    Lines 16-22Branch on operator

    Seed at index 0, else recurse on +, -, and * with the precedence-carry formula for multiplication.

Make it stick

Edge cases, mistakes, and one self-check

E

Edge cases to test

  • Single digit equal to target returns [num]
  • Leading zero operands like '05' are forbidden but '0' alone is allowed
  • Intermediate values can exceed 32-bit range; Python big ints handle this naturally
!

Common beginner mistakes

  • Mishandling multiplication precedence by only tracking cur_val
  • Allowing '00' or '01' as operands
  • Forgetting that the first operand takes no leading operator
  • Using eval on untrusted-shaped strings instead of the O(1) carry
Check your understanding

Why is the multiplication update cur_val - last + last * val rather than cur_val * val?