Assume that you are given a set of coin types (maximum 20 distinct types) and from each type you have maximum 10^5 instances, such that the total number of all the coins in your list is maximum 10^6. What is the number of distinct sums you can make from non-empty groupings of these coins.
for example, you are given the following lists:
coins=[10, 50, 100]
quantity=[1, 2, 1]
which means you have 1 coin of 10, and 2 coins of 50, and 1 coin of 100.
Now the output should be
possibleSums(coins, quantity) = 9.
Here are all the possible sums:
50 = 50;
10 + 50 = 60;
50 + 100 = 150;
10 + 50 + 100 = 160;
50 + 50 = 100;
10 + 50 + 50 = 110;
50 + 50 + 100 = 200;
10 + 50 + 50 + 100 = 210;
10 = 10;
100 = 100;
10 + 100 = 110.
As you can see, there are 9 distinct sums that can be created from non-empty groupings of your coins. Notice that the case of sum=110 can be obtained by either 50+50+10 or 100+10 which should be counted only once.
I approached this problem by generating the list of all the possible subsets and checking if the sum of each subset exists in the list of generated sums so far. If no, I would add the sum to the list and proceed.
Here is the code that I've written and works with the small lists:
def possibleSums(coins, quantity):
if coins is None: return None
subsets = [[]]
sums = set()
next = []
for coin, quant in zip(coins, quantity):
for q in range(quant):
for subs in subsets:
s = sum(subs + [coin])
if not s in sums:
next.append(subs + [coin])
sums.add(s)
subsets += next
next = []
return len(subsets)-1
But this approach does not work with very large input list? For example:
coins = [1, 2]
quantity = [50000, 2]
where it needs to generate 2^50002 subsets and check their corresponding sums, or the following example:
coins = [1, 2, 3]
quantity = [2, 3, 10000]
I think that there should be a solution which doesn't require generating all the subsets, but I have no idea how it should be solved.
Any idea?
The next code uses dynamic programming to avoid exponential complexity (while complexity depends on the number of possible sums and coin quantity). My Python skills are weak, so optimizations might be possible.
P.S. Classic DP uses array of length=1+overall sum of all coins
, here I tried with sets.
def possibleSums(coins, quantity):
sumset = set()
tempset = set()
sumset.add(0)
for ic in range(len(coins)):
coin = coins[ic]
for q in range(quantity[ic]):
val = (q + 1) * coin
for s in sumset:
if not (s + val) in sumset:
tempset.add(s+val)
sumset = sumset | tempset
tempset.clear()
return len(sumset) - 1
print(possibleSums([3,5], [3,2]))
print(possibleSums([5,13,19], [10000,10,2]))
来源:https://stackoverflow.com/questions/48783747/number-of-distinct-sums-from-non-empty-groupings-of-possibly-very-large-lists