DEV Community

Cover image for Count Subsets With a Given Difference: Two Equations, One DP Problem
Nishant Gaurav
Nishant Gaurav

Posted on

Count Subsets With a Given Difference: Two Equations, One DP Problem

Chapter 5 reduced a two-subset problem to a one-number search using algebra. This chapter does the same thing, but this time the algebra hands you a direct answer instead of a search range.

The last chapter asked: which subset sum S1 minimises |R - 2S1|? This chapter asks: given that S1 - S2 = D, how many ways can that partition happen?

Different question. Same two equations. Same Count Subset Sum DP you already know.


The Problem

Given an array and a difference D, count the number of ways to divide the array into two subsets S1 and S2 such that S1 - S2 = D.

arr = [1, 1, 2, 3]
D = 1

Find all partitions where the difference between subset sums is exactly 1.
Enter fullscreen mode Exit fullscreen mode

The Algebra (Again)

You've seen this setup before. Every element goes into either S1 or S2, so:

S1 + S2 = R     (R = total sum)
S1 - S2 = D     (given)
Enter fullscreen mode Exit fullscreen mode

Add both equations:

S1 + S2 = R
S1 - S2 = D
───────────────
2S1     = R + D

S1 = (R + D) / 2
Enter fullscreen mode Exit fullscreen mode

You don't need to find both subsets. Find one subset whose sum equals (R + D) / 2. Count how many such subsets exist. That count is your answer.

Count Subsets With Given Difference just became Count Subset Sum.


Two Checks Before You Touch the DP

Both of these need to pass before computing S1 = (R + D) / 2.

Check 1: |D| <= R

The maximum difference between two subsets is the total sum itself (one subset gets everything, the other gets nothing). If D exceeds R, the partition is impossible.

if abs(diff) > total:
    return 0
Enter fullscreen mode Exit fullscreen mode

Check 2: (R + D) must be even

S1 = (R + D) / 2 must be an integer because subset sums are always integers. If R + D is odd, no valid partition exists.

if (total + diff) % 2 != 0:
    return 0
Enter fullscreen mode Exit fullscreen mode


The DP: Count Subset Sum (Returning Again)

The transition is identical to Chapter 4. Store the count of subsets, combine with +, initialise only T[0][0] = 1, and loop j from 0 not 1.

class Solution:

    def subsetSum(self, arr, subset):

        n = len(arr)

        # T[i][j] = number of subsets using first i elements
        # whose sum is exactly j
        T = [[0] * (subset + 1) for _ in range(n + 1)]

        # Only base case: one way to make sum 0
        # with zero elements — the empty subset
        T[0][0] = 1

        for i in range(1, n + 1):

            # Start from 0 — zeros must flow through
            # the transition naturally
            for j in range(subset + 1):

                if arr[i - 1] <= j:
                    # Count ways from both choices
                    T[i][j] = (
                        T[i - 1][j - arr[i - 1]]  # include
                        +
                        T[i - 1][j]                # exclude
                    )
                else:
                    # Element too large — must exclude
                    T[i][j] = T[i - 1][j]

        return T[n][subset]


    def countPartitions(self, arr, diff):

        total = sum(arr)

        # Partition is impossible if difference exceeds total
        if abs(diff) > total:
            return 0

        # S1 = (R+D)/2 must be an integer
        if (total + diff) % 2 != 0:
            return 0

        # Directly calculated — no searching needed
        subset = (total + diff) // 2

        return self.subsetSum(arr, subset)
Enter fullscreen mode Exit fullscreen mode

Target Sum: The Same Problem in Disguise

LeetCode's Target Sum problem asks something that looks completely different: given an array of numbers, assign a + or - sign to every element. Count the ways to reach a specific target.

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

+1 -1 -2 +3 = 1  ✓
+1 +1 +2 -3 = 1  ✓
...
Enter fullscreen mode Exit fullscreen mode

It feels like a sign-assignment problem. It isn't. It's two subsets in disguise.

Every element with a + sign belongs to S1. Every element with a - sign belongs to S2. The final expression S1 - S2 must equal target. That gives you:

S1 - S2 = target
S1 + S2 = total

 S1 = (total + target) / 2
Enter fullscreen mode Exit fullscreen mode

Count the subsets with sum S1. You're done.


Target Sum Code

The logic is identical to Count Partitions. Only the variable names change.

class Solution:

    def subsetSum(self, nums, subset):

        n = len(nums)

        # T[i][j] = number of subsets using first i elements
        # whose sum is exactly j
        T = [[0] * (subset + 1) for _ in range(n + 1)]

        # One way to make sum 0: empty subset
        T[0][0] = 1

        for i in range(1, n + 1):

            # Start from 0 for correct zero handling
            for j in range(subset + 1):

                if nums[i - 1] <= j:
                    # Count both choices
                    T[i][j] = (
                        T[i - 1][j - nums[i - 1]]  # include
                        +
                        T[i - 1][j]                 # exclude
                    )
                else:
                    T[i][j] = T[i - 1][j]

        return T[n][subset]


    def findTargetSumWays(self, nums, target):

        total = sum(nums)

        # target cannot exceed the total range
        if abs(target) > total:
            return 0

        # S1 = (total + target)/2 must be an integer
        if (total + target) % 2 != 0:
            return 0

        # Same conversion as Count Partitions
        subset = (total + target) // 2

        return self.subsetSum(nums, subset)
Enter fullscreen mode Exit fullscreen mode

Why These Two Problems Are Identical

Look at them side by side.

Count Partitions Target Sum
Equation S1 - S2 = D S1 - S2 = target
Total S1 + S2 = R S1 + S2 = R
S1 (R + D) / 2 (R + target) / 2
Check 1 `\ D\
Check 2 {% raw %}(R + D) even (R + target) even
DP used Count Subset Sum Count Subset Sum

The difference is semantic, not structural. One problem uses the word "difference," the other uses "target." The algebra is identical. The DP is identical.


The Full Knapsack Pattern Chain


Quick Revision

Count Partitions With Given Difference

S1 - S2 = D
S1 + S2 = R
 S1 = (R + D) / 2

Check 1: abs(D) <= R         else return 0
Check 2: (R + D) % 2 == 0    else return 0

subset = (R + D) // 2
return countSubsetSum(arr, subset)
Enter fullscreen mode Exit fullscreen mode

Target Sum

+ elements = S1
- elements = S2
S1 - S2 = target
 S1 = (R + target) / 2

Check 1: abs(target) <= R
Check 2: (R + target) % 2 == 0

subset = (R + target) // 2
return countSubsetSum(nums, subset)
Enter fullscreen mode Exit fullscreen mode

Both reduce to Count Subset Sum with T[0][0] = 1 and loop starting from j = 0.


What You Now Understand

Six problems deep. The Knapsack chain is now complete for the 0/1 pattern. Every problem reused either Subset Sum or Count Subset Sum with one mathematical step in front of it. The algebra was the same twice: two equations, one variable, one direct target.

The pattern to carry forward is simple. When you see two subsets and a given difference, write S1 - S2 = D and S1 + S2 = R, add them, and you'll have the subset sum you need to count. The two checks (|D| <= R and (R + D) is even) guard against edge cases before the DP even starts.

The next part of the series moves into Unbounded Knapsack, where the structure shifts: instead of each item being available at most once, an item can be chosen as many times as needed. The choice diagram changes. The table direction changes. The core thinking stays exactly the same.

Top comments (0)