</> MAANG.io
coding interview · 301

Advanced

Advanced coding interview preparation covering complex algorithms, system design, and optimization techniques for senior-level positions.

0/95 solved 0% complete

Counting and Bitmask DP

What is this?

Two of these problems have a transition that sums a whole range of earlier states — which is correct, and too slow. Both collapse to a sliding window by writing the recurrence twice and subtracting. The other three are about state: a ± assignment problem that turns out to be subset sum, and two searches whose state is "what still needs covering" rather than an index.

flowchart TD A["Counting and Bitmask"] --> B["summed transition"] A --> C["state = what's left"] B --> B1["K Inverse Pairs
dp[n][k] = Σ dp[n−1][k−j]"] B1 --> B2["subtract adjacent k → 3 terms"] B --> B3["New 21 Game
dp[i] = mean of the last W states"] B3 --> B4["running window sum"] C --> C1["Target Sum → subset sum"] C --> C2["Stickers → remaining letters"] C --> C3["Word Break II → remaining suffix"]

💡 Fun fact: Target Sum asks how many ways to put + or in front of each number to reach a target, and looks like 2ⁿ enumeration. Let P be the numbers you make positive and N the rest. Then P − N = target and P + N = total, so P = (total + target) / 2 — a fixed number. The question collapses to "how many subsets sum to P", an ordinary 0/1 knapsack count. As a bonus, if total + target is odd or |target| > total the answer is instantly 0. Turning a signed-assignment problem into a subset sum by adding the two equations is a move worth keeping.

🔓 The 5 problems in this chapter are free. Sign in with Google or Microsoft to start solving.


The one-line idea: if a transition sums many earlier states, write it for k and for k−1 and subtract. Nearly every term cancels, and an entire dimension of work disappears.


1. Collapse the sum

The natural recurrence for K Inverse Pairs — inserting the n-th element can create 0 to n−1 new inversions — is a range sum:

dp[n][k] = dp[n-1][k] + dp[n-1][k-1] + … + dp[n-1][k-n+1]

Write the same line for k−1 and subtract. Everything cancels except the two edges:

dp[n][k] = dp[n][k-1] + dp[n-1][k] - dp[n-1][k-n]

O(n²k) becomes O(nk) and the code shrinks. Two details bite: dp[n-1][k-n] only exists when k ≥ n, and the subtraction can go negative before the modulo, so normalise after every step.

2. The same move, as a window

New 21 Game draws uniformly from 1 … maxPts while below k, and asks for the probability of finishing at or below n. Each state is the mean of the previous maxPts states — the same summed transition, so the same fix:

dp[0], window, ans = 1.0, 1.0, 0.0
for i in range(1, n + 1):
    dp[i] = window / maxPts
    if i < k: window += dp[i]                      # still drawing
    else:     ans   += dp[i]                       # stopped here, and it counts
    if 0 <= i - maxPts < k: window -= dp[i-maxPts]  # slide the window

The guard is exact: a state leaves the window only if it was ever in it, which requires i - maxPts < k. The early exit if k == 0 or n >= k + maxPts - 1: return 1.0 handles the case where stopping below n is certain — and skipping it leaves an array of size n that is never needed.

3. State that is "what remains"

Stickers to Spell Word memoises on the sorted remaining letters, not on an index:

@lru_cache(None)
def go(rem):
    if not rem: return 0
    first = rem[0]                                 # must be covered by SOME sticker
    for c in counts:
        if c[first] == 0: continue                 # ← the pruning that makes it feasible
        ...

Requiring every candidate sticker to contain rem[0] prunes enormously and costs nothing in correctness — that letter has to come from somewhere, so trying stickers that cannot supply it only re-derives orderings already explored. Sorting the remainder is what makes two equivalent states hash to the same key.

Word Break II is the same idea over suffixes, memoised on the start index, returning the list of sentences rather than a count. Memoising is what keeps a string like "aaaaaaaa" with dictionary ["a","aa","aaa"] from re-deriving the same suffix repeatedly — though the output can still be exponential, which is a property of the question.


4. A 30-second worked example (Target Sum)

nums = [1,1,1,1,1], target = 3

total = 5,  target = 3
total + target = 8, even  ✓        P = 8 / 2 = 4

so: how many subsets of [1,1,1,1,1] sum to 4?
    choose 4 of the 5 ones → C(5,4) = 5

answer: 5      (and indeed +1+1+1+1−1 and its four rearrangements)

The check that saves the most time is the parity one. With target = 2, total + target = 7 is odd, no subset sum exists, and the answer is 0 before a table is allocated — a fact no amount of enumeration would have discovered as quickly.


5. Where you'll actually meet this

  • Risk and gaming systems. New 21 Game is a bounded random walk, which is how ruin probabilities are actually computed.
  • Inventory and fulfilment. Stickers is "cover this order from these packs, using as few as possible".
  • Search and autocomplete. Word Break II is segmentation for languages written without spaces.
  • Ranking and sorting analysis. Inversion counts measure how far a ranking is from a reference.
  • Budget and portfolio allocation. Subset-sum counting underlies "how many ways can this be funded exactly".

6. Problems in this chapter

▶ K Inverse Pairs Array

Count arrays with exactly k inverse pairs. The summed transition collapses to three terms by differencing adjacent states.
Pattern: counting DP with a collapsed range sum. Target: O(nk) time, O(k) space.

▶ New 21 Game

Probability of stopping at or below n. Each state is the mean of a fixed window of earlier states, maintained as a running sum.
Pattern: probability DP with a sliding window. Target: O(n) time, O(n) space.

▶ Target Sum

Count ± assignments reaching a target. Solve for the positive subset's sum and count subsets that reach it.
Pattern: subset-sum counting. Target: O(n · sum) time, O(sum) space.

▶ Stickers to Spell Word

Fewest stickers spelling a target. Memoise on the sorted remaining letters and only try stickers covering the first one.
Pattern: memoised search over remaining state. Target: exponential worst case, fast with the pruning.

▶ Word Break II

Every sentence formable from the dictionary. Memoise on the start index and return the list of completions of each suffix.
Pattern: memoised backtracking. Target: output-bound.


7. Common pitfalls 🚫

  • Leaving the summed transition in place. It passes the samples and times out on the real constraints.
  • Reading dp[n-1][k-n] when k < n. That term does not exist and must be guarded.
  • Taking a modulo of a negative. Normalise after every subtraction.
  • Sliding the probability window unconditionally. A state only leaves if it ever entered — i - maxPts < k.
  • Missing the parity check in Target Sum, which decides many inputs instantly.
  • Memoising stickers on an unsorted remainder, so equivalent states never share a cache entry.
  • Dropping the first-letter pruning, which is the difference between fast and hopeless.

8. Key takeaways

  1. A summed transition is a signal, not a solution. Difference adjacent states and it collapses.
  2. A sliding window is the same trick wearing a probability hat.
  3. Add the two equations. P − N = target with P + N = total turns signs into a subset sum.
  4. State can be "what is left" rather than "how far you have come".
  5. Canonicalise the memo key — sort the remainder, or equivalent states never merge.
  6. A forced-coverage pruning is free correctness: the first uncovered letter must come from somewhere.
  7. Why interviewers like it: the naive recurrence is easy and quadratic, so the optimisation is precisely the thing being measured.

Order: K Inverse Pairs Array → New 21 Game → Target Sum → Stickers to Spell Word → Word Break II.

Target Sum

Core idea: You're given an array of non-negative integers and a target. Put a + or a - in front of every number, then add them up; count how many sign assignments make the total equal target. Brute force tries all 2^n sign patterns, but there's a clean reduction. Split the numbers into the set P that gets + and the set N that gets -. Then P - N = target and P + N = total, so adding those gives P = (total + target) / 2. The whole problem collapses to: how many subsets of nums sum to P? That's a textbook 0/1 subset-sum counting knapsackdp[s] = number of subsets summing to s, updated per number with dp[s] += dp[s - num] iterating s descending so each number is used at most once. First guard the reduction: if total + target is odd or |target| > total, the answer is 0. O(n·sum) time.


The problem, rephrased

You're packing a delivery van and every parcel has a fixed weight. For each parcel you either load it onto the van (it pushes the scale up) or hand it to the return driver (it pulls the scale down by the same amount). At the end of the day the dispatcher wants the net weight on your manifest — loaded minus returned — to read exactly some agreed number. Every parcel must go one way or the other; none can be skipped. The dispatcher doesn't want one valid plan, they want to know how many distinct load/return plans hit that net number exactly.

Strip the story away: "parcels" are array elements, "load / return" are the + / - signs, and "net weight" is target.

Formally: given an integer array nums (non-negative) and an integer target, prefix each nums[i] with + or - so that the resulting signed sum equals target. Return the number of different ways to do this.

This is LeetCode 494 — Target Sum.

Input Means Output
nums = [1,1,1,1,1], target = 3 five 1's, want net +3 5
nums = [1], target = 2 one parcel can only make +1 or -1 0 (impossible)
nums = [1,0], target = 1 the 0 can take either sign for free 2

Note the second column for [1,0]: +1+0, +1-0 both equal 1, and -0 versus +0 are counted as distinct assignments even though they have the same value. That zero-handling subtlety is the classic trap — we handle it correctly below.


Sign in to continue reading

The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.

Sign in to read the full lesson

Sign in to MAANG.io

Use your Google or Microsoft account — no password to remember.

Continue with Google Continue with Microsoft

Please accept the terms above to continue.