Lesson 51 — DP V: 0/1 knapsack

~25 minutes · Day 65 · dynamic programming

Tonight's interview shape is Partition Equal Subset Sum: given positive integers, decide whether they can be split into two groups with the same total. The trick is not to build the two groups directly. The trick is to ask whether one group can hit the exact half-sum.

The invariant

Ask “can some subset hit this exact target?” where target = totalSum/2; each item is usable once, so sweep targets from high to low.

That sentence is the pattern. If the total sum is odd, there is no equal split. If the total sum is even, the whole problem becomes one yes/no question: can some subset make totalSum / 2?

Partition: the slow way first

The brute force is to try every subset: take or skip each number, then check whether one path reaches the target. That is O(2^n) time because every item doubles the number of possibilities. It is correct, but it grows too fast for interview input sizes.

def brute(nums, i, target):
    if target == 0: return True
    if i == len(nums) or target < 0: return False
    return brute(nums, i + 1, target - nums[i]) or brute(nums, i + 1, target)

Dynamic programming keeps the useful part of that recursion: the reachable sums. Instead of asking the same “can I make sum s?” question again and again, store each answer in a boolean array.

Partition: the DP way

Use the four DP questions from the training plan:

def canPartition(nums):
    total = sum(nums)                         # Python's built-in sum
    if total % 2 == 1:
        return False                          # odd total cannot split evenly
    target = total // 2
    dp = [False] * (target + 1)
    dp[0] = True                              # empty subset makes 0
    for x in nums:
        for s in range(target, x - 1, -1):    # high to low: use x once
            dp[s] = dp[s] or dp[s - x]
    return dp[target]

sum gives the total, and range can count downward with a negative step. The high-to-low sweep is the part to protect. If you sweep upward, dp[s - x] might have been created by the same x, which accidentally turns a 0/1 choice into an unlimited-use choice.

The state space

0/1 knapsack one-dimensional DP transition A row of target cells from zero to eleven. An arrow shows that with item five, dp eleven can become true if dp six was already true. A second arrow shows the high to low sweep. Example target = 11, current item x = 5 sweep targets high to low 0 1 2 3 4 5 6 7 8 9 10 11 transition: dp[11] = dp[11] or dp[6] s - x s
The arrow says the whole recurrence: when x = 5, target 11 can be reached if target 6 was reachable before this item.

Transfer: same question, new costume

Suppose the question is smaller: with nums = [2, 3, 7, 8], can some subset hit target 10? Before opening the reveal, say the state, transition, base case, and answer location out loud.

Your prediction first — then reveal.

The same 0/1 knapsack state works: dp[s] means a processed subset can make s. Start with dp[0] = True. For each number, sweep s from 10 down to that number. The answer is dp[10], which becomes true because 2 + 8 = 10.

What the trade buys you

ApproachTimeSpace
Brute force (try every subset)O(2^n)O(n)
0/1 knapsack DP (reachable sums)O(n * target)O(target)

The trade is memory for repeated work. The boolean row remembers which sums are reachable, so each item updates each target once.

Practice — answer before you scroll past

1. What does dp[s] mean after processing some items?

2. Why sweep target from high to low?

3. Spot the bug in this update:

for x in nums:
    for s in range(x, target + 1):
        dp[s] = dp[s] or dp[s - x]

4. Which prompt is this pattern in disguise?

Your move (tonight)

Solve this on LeetCode, logging it in your Notion tracker with the cycle — predict → attempt → compare → encode:

  1. Partition Equal Subset Sum — predict the half-sum target, attempt the high-to-low DP, compare after your attempt, then encode the invariant in your own words.

For the encode step, write four short sentences: state, transition, base case, answer location. That is the DP self-check gate for this lesson.

One primary source

Watch NeetCode — Partition Equal Subset Sum after your attempt, as the compare step. Find the exact sentence where his reasoning diverges from yours.