Reputation: 36745
What is an efficient way to enumerate all subsets of a given list L of numbers, such that the sum of all numbers in the set is at most a constant S?
One option is to use the recipe for powerset
from itertools
, and then filter by the sum, like this:
for subset in powerset(L):
if sum(subset) <= S:
yield subset
But this may be very wasteful, since the number of subsets may be very large, and only a small number of them have a sum of at most S. What is a more efficient way to do this?
Upvotes: 0
Views: 70
Reputation: 80187
You can generate all subsets with sums <= S
but note that storing them might require a lot of space. For "dense" subset sum distribution we can use a list, where A[k]
keeps list of subsets with sum k
. For sparse sums it would be better to use dictionary where dict[key]
keeps list of subsets with sum key
(remember copy of dictionary for every x, update dictionary adding x to existing subsets from that copy)
L = [1,3,5,8,11,17, 19, 23]
S = 15
A = [[] for _ in range(S+1)]
A[0] = [[0]] #fake item to make non-zero list
for x in L:
for ss in range(S, x-1,-1):
l = len(A[ss-x])
if len(A[ss-x]):
for Y in A[ss-x]:
A[ss].append(Y + [x])
for a in A:
for b in a:
if len(b) > 1:
print(b[1:], end = ',')
print()
[1],
[3],
[1, 3],
[5],
[1, 5],
[3, 5],[8],
[1, 3, 5],[1, 8],
[3, 8],[11],
[1, 3, 8],[1, 11],
[5, 8],
[1, 5, 8],[3, 11],
[1, 3, 11],
Upvotes: 1