Number of distinct sums from non-empty groupings of (possibly very large) lists

旧街凉风 提交于 2019-12-22 01:23:33

问题


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?


回答1:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!