CMD Guide
HomeDSADynamic Programming

Subset Sum

Subset Sum decides reachability of a target total by building up, from the empty set, the complete set of sums achievable using each prefix of items — a boolean version of 0/1 Knapsack where the only "value" that matters is whether a sum is hit at all, so overlapping include/exclude sub-decisions can be memoized instead of re-explored.

Recognize the pattern

Brute force to optimal

Brute force: for each item, recursively branch on include vs exclude, checking if the remaining target reaches 0. Every item doubles the state space regardless of repeated (index, remainingSum) pairs — cost O(2^n) time, O(n) recursion-depth space.

Optimal: notice the recursion state is fully described by (index, remainingSum), and remainingSum only ranges over [0, S]. Cache it: dp[i][s] = can items 0..i-1 sum to s. That collapses the exponential tree into a table of (n+1) x (S+1) cells, each computed in O(1) from cells already known.

Complexity, derived

Recurrence: dp[i][s] = dp[i-1][s] || (s >= item[i-1] && dp[i-1][s-item[i-1]]), base dp[i][0] = true, dp[0][s>0] = false.

Traced example

Set {1, 2, 3, 7}, target S = 6. Building dp[i][s] row by row (rows = items considered so far, T = reachable):

after items=0123456
noneTFFFFFF
+1TTFFFFF
+2TTTTFFF
+3TTTTTTT

After including item 3 (value 3), dp[6] = dp_prev[6] (F) OR dp_prev[6-3=3] (T) = T — reached via subset {1, 2, 3}. Item 7 is never needed once 6 is already reachable.

Code

class SubsetSum {
    static boolean canPartition(int[] items, int target) {
        boolean[] dp = new boolean[target + 1];
        dp[0] = true;
        for (int item : items) {
            for (int s = target; s >= item; s--) {
                dp[s] = dp[s] || dp[s - item];
            }
        }
        return dp[target];
    }

    public static void main(String[] args) {
        System.out.println(canPartition(new int[]{1, 2, 3, 7}, 6)); // true
        System.out.println(canPartition(new int[]{1, 3, 4, 8}, 6)); // false
    }
}

Pitfalls

When to use / when not

Use the DP when target S is polynomially bounded (interview-sized inputs, or real constraints like currency amounts). It beats brute force's O(2^n) whenever n*S < 2^n, which is almost always for reasonable S.

Avoid it when S is astronomically large (e.g., S ~ 10^15) relative to n — then O(n*S) is worse than exponential-but-small-n brute force, and you instead want meet in the middle: split items into two halves, enumerate all 2^(n/2) subset sums per half, sort one half and binary-search/two-pointer against the other — O(2^(n/2) log(2^(n/2))) time, O(2^(n/2)) space, independent of S. Meet-in-the-middle trades a much smaller time bound for higher constant-factor complexity in implementation and is the right call once n ≤ ~40 but S is huge.

Takeaways

Recall: Why must the inner loop over sums run from high to low when using a single rolling array for 0/1 Subset Sum, and what would break if it ran low to high?


Synthesized from the study guide's DP/Subset Sum notes, cross-checked against the standard 0/1 Knapsack reduction and meet-in-the-middle technique for large-target variants.

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

Stuck on 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 **Subset Sum** (DSA) and want to truly understand it. Explain 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 **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 **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 **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