簡體   English   中英

查找所有總計為給定數字的可能子集

[英]Find all possible subsets that sum up to a given number

我正在學習Python,對此問題似乎很簡單。

我想找到所有總計給定數字的可能組合。
例如:4-> [1,1,1,1] [1,1,2] [2,2] [1,3]

我選擇生成所有可能的子集(2 ^ n)的解決方案,然后得出總和等於數字的那些子集。 我的狀況有問題。 碼:

def allSum(number):
    #mask = [0] * number
    for i in xrange(2**number):
        subSet = []
        for j in xrange(number):
            #if :
                subSet.append(j)
        if sum(subSet) == number:
           yield subSet



for i in allSum(4):
    print i   

BTW是個好方法嗎?

這是幾年前我看到的一些實現此目的的代碼:

>>> def partitions(n):
        if n:
            for subpart in partitions(n-1):
                yield [1] + subpart
                if subpart and (len(subpart) < 2 or subpart[1] > subpart[0]):
                    yield [subpart[0] + 1] + subpart[1:]
        else:
            yield []

>>> print list(partitions(4))
[[1, 1, 1, 1], [1, 1, 2], [2, 2], [1, 3], [4]]

其他參考文獻:

該解決方案不起作用,對嗎? 它永遠不會將一個數字加到子集上一次,因此您將永遠不會得到例如[1,1,2]。 它也永遠不會跳過數字,因此您永遠也不會得到例如[1,3]。

因此,解決方案存在兩個問題:第一,實際上並沒有生成1..number范圍內的所有可能子集。 第二,所有子集的集合將排除您應包括的內容,因為它不允許數字出現多次。

這種問題可以概括為搜索問題。 想象一下,您想嘗試的數字是一棵樹上的節點,然后您可以使用深度優先搜索來找到代表該解決方案的所有路徑。 它是一棵無限大的樹,但是幸運的是,您不需要搜索所有的樹。

這是一種替代方法,該方法通過獲取全1的列表並通過添加后續元素來遞歸折疊它來工作,這比生成所有可能的子集更有效:

def allSum(number):
    def _collapse(lst):
        yield lst
        while len(lst) > 1:
            lst = lst[:-2] + [lst[-2] + lst[-1]]
            for prefix in _collapse(lst[:-1]):
                if not prefix or prefix[-1] <= lst[-1]:
                    yield prefix + [lst[-1]]
    return list(_collapse([1] * number))

>>> allSum(4)
[[1, 1, 1, 1], [1, 1, 2], [2, 2], [1, 3], [4]]
>>> allSum(5)
[[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 2, 2], [1, 1, 3], [2, 3], [1, 4], [5]]

如果您不希望出現這種情況,則可以去除最后一個值。 如果您只是要遍歷結果,請刪除list調用並返回生成器。

這等效於此問題中描述的問題,並且可以使用類似的解決方案。

詳細說明:

def allSum(number):
    for solution in possibilites(range(1, number+1), number):
        expanded = []
        for value, qty in zip(range(1, number+1), solution):
            expanded.extend([value]*qty)
        yield expanded

這就把這個問題翻譯成那個問題,然后又回來了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM