CMD Guide
HomeDSADynamic Programming

Count of Subset Sum

Counting subsets that sum to a target works by building, for every prefix of the array and every achievable partial sum, the number of ways to reach that sum — each new element either joins existing subsets (carrying their count forward into a larger sum) or is skipped, so the count at dp[sum] accumulates contributions from both choices instead of just a yes/no reachability flag.

Recognize the pattern

Brute force → optimal

Brute force: recurse on each index with a choice to include or exclude it, summing the count of ways from both branches; base case succeeds when the running sum hits 0. This explores every subset: O(2n) time, O(n) recursion stack.

Optimal: the recursion only depends on (index, remainingSum), and remainingSum ranges over just 0..S — a classic overlapping-subproblems + optimal-substructure signature, so memoize or tabulate into a 2-D (or rolled 1-D) DP: O(n·S) time, O(S) space.

Complexity from first principles

Let dp[s] = number of ways to form sum s using elements processed so far. Recurrence per new element num:

dp_new[s] = dp_old[s]                 // exclude num
          + dp_old[s - num]  (if s >= num)   // include num

There are n elements, each requiring a pass over S+1 sum slots → exactly n·(S+1) constant-time updates: Time O(n·S). Only the previous row is ever read, so one array of length S+1 suffices, iterated right-to-left per element to avoid reusing an item twice in the same pass: Space O(S) (O(n·S) if you keep the full 2-D table for traceability/teaching).

Worked example

Input {1, 1, 2, 3}, S = 4. Rows = elements processed so far, columns = sum 0..4, dp[0]=1 always (empty subset makes sum 0). Each cell reads only the previous row's values (right-to-left pass), which is what keeps this 0/1 rather than unbounded.

after01234
{}10000
+111000
+112100
+212221
+312233

Trace the last two rows by hand: before processing 2, dp = [1,2,1,0,0]. Reading old values right-to-left, dp[4] += dp[2]=1 (→1), dp[3] += dp[1]=2 (→2), dp[2] += dp[0]=1 (→2), giving [1,2,2,2,1]. Then processing 3: dp[4] += dp[1]=2 (→1+2=3), dp[3] += dp[0]=1 (→2+1=3), giving the final row [1,2,2,3,3]. dp[4] = 3 matches direct enumeration: {1,1,2}, {1,3} using the first 1, and {1,3} using the second 1 — three position-distinct subsets, exactly what the recurrence counts.

Reference implementation (Java)

static int countSubsetSum(int[] nums, int S) {
    int[] dp = new int[S + 1];
    dp[0] = 1; // empty subset makes sum 0
    for (int num : nums) {
        for (int s = S; s >= num; s--) {
            dp[s] += dp[s - num];
        }
    }
    return dp[S];
}

Pitfalls

When to use / when not

Use when items are used at most once, the target is small enough that S fits in memory (pseudo-polynomial, not polynomial in the numeric value of S), and you need a count rather than existence or an optimal value. If S is astronomically large but n is small (≤ ~20), prefer meet-in-the-middle: split into two halves, enumerate all 2n/2 subset sums per half, sort one half and binary-search/count matches against S - sum from the other — O(2n/2·log(2n/2)) time, no dependency on S at all. If you only need existence (not count), the boolean 0/1 knapsack reachability DP is cheaper to reason about and equally O(n·S).

Takeaways

Recall: why must the inner sum loop run from S down to num, not from num up to S?


Pattern generalizes Kadane-adjacent 0/1 knapsack counting; canonical treatment in Grokking the Coding Interview (Subset Sum pattern) and CLRS-style DP-over-subset-sums exercises.

🤖 Don't fully get this? Learn it with Claude

Stuck on Count of Subset Sum? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Count of Subset Sum** (DSA) and want to truly understand it. Explain Count of Subset Sum from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Count of Subset Sum** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Count of Subset Sum** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Count of Subset Sum** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes