Subset Sum and Partition DP: Backtracking vs DP

Sanjeev SharmaSanjeev Sharma
3 min read

Advertisement

Subset Sum: Backtracking vs DP

When to Use Each

  • Backtracking: When you need ALL solutions, not just existence/count
  • DP: When you only need existence, count, or optimal value
  • Backtracking + Pruning: When n is small but target is large

Backtracking (enumerate all solutions)

def subset_sum_all(nums, target):
    result = []
    nums.sort()
    def bt(start, current, remaining):
        if remaining == 0:
            result.append(current[:])
            return
        for i in range(start, len(nums)):
            if nums[i] > remaining: break  # pruning
            current.append(nums[i])
            bt(i + 1, current, remaining - nums[i])
            current.pop()
    bt(0, [], target)
    return result

# DP (existence only)
def subset_sum_exists(nums, target):
    dp = {0}
    for n in nums:
        dp |= {x + n for x in dp}
    return target in dp

# DP (count ways)
def subset_sum_count(nums, target, mod=10**9+7):
    dp = [0] * (target + 1)
    dp[0] = 1
    for n in nums:
        for t in range(target, n-1, -1):  # reverse to avoid reuse
            dp[t] = (dp[t] + dp[t-n]) % mod
    return dp[target]

# DP (min elements to reach target)
def subset_sum_min(nums, target):
    dp = [float('inf')] * (target + 1)
    dp[0] = 0
    for n in nums:
        for t in range(n, target + 1):  # forward: reuse allowed
            dp[t] = min(dp[t], dp[t-n] + 1)
    return dp[target] if dp[target] != float('inf') else -1

Bitset Optimization (C++)

#include <bits/stdc++.h>
using namespace std;

// O(n * target / 64) with bitset
bool subsetSumBitset(vector<int>& nums, int target) {
    bitset<100001> dp;
    dp[0] = 1;
    for (int n : nums) dp |= dp << n;
    return dp[target];
}

Java Implementation

public class SubsetSum {
    // Count subsets with given sum
    public int countSubsets(int[] nums, int target) {
        int MOD = 1_000_000_007;
        int[] dp = new int[target + 1];
        dp[0] = 1;
        for (int n : nums)
            for (int t = target; t >= n; t--)
                dp[t] = (dp[t] + dp[t - n]) % MOD;
        return dp[target];
    }
}

Comparison Table

ApproachTimeSpaceUse Case
BacktrackingO(2^n)O(n)Enumerate all
DP (existence)O(n*T)O(T)Can we reach T?
DP (count)O(n*T)O(T)How many ways?
DP (min elements)O(n*T)O(T)Min elements
BitsetO(n*T/64)O(T/8)Large T, existence only

LeetCode Problems

  • 39. Combination Sum — backtracking
  • 40. Combination Sum II — backtracking no reuse
  • 416. Partition Equal Subset Sum — DP
  • 494. Target Sum — DP (count ways)
  • 322. Coin Change — DP (min coins)

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro