Get all numbers that add up to a number
Categories:
Finding All Subsets That Sum to a Target Number in Python

Explore various Python techniques to identify all combinations of numbers from a given set that sum up to a specific target value. This article covers recursive, iterative, and dynamic programming approaches.
The problem of finding all subsets of numbers that add up to a specific target sum is a classic computer science challenge, often referred to as the Subset Sum Problem. It has applications in various fields, including finance (portfolio optimization), logistics (knapsack problem variations), and game development. This article will guide you through different methods to solve this problem efficiently in Python, focusing on clarity and practical implementation.
Understanding the Subset Sum Problem
Given a set of non-negative integers and a target sum S
, the goal is to find all unique subsets of the given set whose elements sum up to S
. For example, if the set is [1, 2, 3]
and the target sum is 3
, the valid subsets are [1, 2]
and [3]
. This problem can be approached using several algorithmic paradigms, each with its own trade-offs in terms of performance and complexity.
flowchart TD A[Start with empty subset and target sum] --> B{Is current sum == target?} B -- Yes --> C[Add subset to results] B -- No --> D{Are there more numbers to consider?} D -- Yes --> E{Choose next number} E --> F[Include number in subset] F --> A E --> G[Exclude number from subset] G --> A D -- No --> H[Backtrack] C --> H H --> I[End]
Conceptual flow for finding subsets that sum to a target.
Recursive Backtracking Approach
A common and intuitive way to solve the subset sum problem is through recursion with backtracking. This method explores all possible combinations by deciding for each number whether to include it in the current subset or not. When the current sum matches the target, the subset is recorded. If the current sum exceeds the target or all numbers have been considered, the function backtracks.
def find_subsets_recursive(numbers, target_sum):
results = []
current_subset = []
def backtrack(index, current_sum):
if current_sum == target_sum:
results.append(list(current_subset))
return
if current_sum > target_sum or index == len(numbers):
return
# Include the current number
current_subset.append(numbers[index])
backtrack(index + 1, current_sum + numbers[index])
current_subset.pop() # Backtrack
# Exclude the current number
backtrack(index + 1, current_sum)
backtrack(0, 0)
return results
# Example usage:
numbers = [1, 2, 3, 4, 5]
target = 7
print(f"Numbers: {numbers}, Target: {target}")
print(f"Subsets: {find_subsets_recursive(numbers, target)}")
numbers_dup = [1, 1, 2, 3]
target_dup = 3
print(f"\nNumbers: {numbers_dup}, Target: {target_dup}")
print(f"Subsets: {find_subsets_recursive(numbers_dup, target_dup)}")
Python implementation of the recursive backtracking approach.
Dynamic Programming Approach (Counting Subsets)
While the recursive backtracking approach finds all subsets, a dynamic programming approach is often used when you only need to count the number of subsets that sum to the target, or to check if such a subset exists. For finding all subsets, DP can be adapted but becomes more complex to store the actual subsets rather than just counts or boolean flags. Here, we'll illustrate the DP approach for counting subsets, which lays a foundation for more complex DP solutions.
def count_subsets_dp(numbers, target_sum):
# dp[i][j] will be true if sum j is possible with first i numbers
# For counting, dp[j] will store the number of ways to get sum j
dp = [0] * (target_sum + 1)
dp[0] = 1 # One way to make sum 0 (by choosing no elements)
for num in numbers:
# Iterate from target_sum down to num
# This ensures each number is used at most once per combination
for j in range(target_sum, num - 1, -1):
dp[j] += dp[j - num]
return dp[target_sum]
# Example usage:
numbers = [1, 2, 3]
target = 3
print(f"\nNumbers: {numbers}, Target: {target}")
print(f"Number of subsets (DP): {count_subsets_dp(numbers, target)}")
numbers_large = [1, 5, 11, 5]
target_large = 11
print(f"\nNumbers: {numbers_large}, Target: {target_large}")
print(f"Number of subsets (DP): {count_subsets_dp(numbers_large, target_large)}")
Dynamic programming solution to count subsets with a given sum.
dp
table would need to store lists of subsets instead of just counts, significantly increasing memory usage and complexity. For finding all subsets, recursive backtracking is generally more straightforward to implement.