2015-04-05 33 views
1

所以我想打印出來的初始集合加起來21的所有子集到目前爲止,我只能想出這個子集和帶回溯Python的

def twentyone(array, num=21): 
    if len(array) == 0: 
     return None 
    else: 
     if array[0] == num: 
      return [array[0]] 
     else: 
      with_v = twentyone(array[1:], (num - array[0])) 
      if with_v: 
       return [array[0]] + with_v 
      else: 
       return twentyone(array[1:], num) 

它確實給瞭解決方案,但只有第一個。我如何改變它,以便它能給我所有可能的子集。我試過做了一些改變,但它只給我嵌套列表。你能幫忙的話,我會很高興。

回答

3

您可以創建一個遞歸發生器:

def twentyone(array, num=21): 
    if num < 0: 
     return 
    if len(array) == 0: 
     if num == 0: 
      yield [] 
     return 
    for solution in twentyone(array[1:], num): 
     yield solution 
    for solution in twentyone(array[1:], num - array[0]): 
     yield [array[0]] + solution 

例如:

>>> list(twentyone([5, 16, 3, 2])) 
[[16, 3, 2], [5, 16]] 
+0

你的回答是對的。然而,如果我有一個輸入,如何提高運行時間。下面的一個。我被告知要做簡單的修剪。我如何拿出已經存在的解決方案? SEQ = [10] + [22]×50 + [11] 打印(排序(twentyone(SEQ))) @JuniorCompressor – 2015-04-05 11:59:13

+0

我更新了我的答案來處理你給 – JuniorCompressor 2015-04-05 12:06:05

+0

感謝例子。這對我非常有幫助。 @JuniorCompressor – 2015-04-05 22:37:31

0

如果你被允許使用標準Python庫,這裏是一個較短的解決方案:

import itertools 
import operator 


def twentyone(array, num=21): 
    subsets = reduce(operator.add, [list(itertools.combinations(array, r)) for r in range(1, 1 + len(array))]) 
    return [subset for subset in subsets if sum(subset) == num] 


print twentyone([1, 2, 5, 6, 8, 9, 10]) 

結果:

[(2, 9, 10), (5, 6, 10), (1, 2, 8, 10), (1, 5, 6, 9), (2, 5, 6, 8)] 
+0

這是非常低效的,OP已經特別標記了'遞歸'和'回溯'。 – thefourtheye 2015-04-05 11:08:07

+0

@thefourtheye足夠公平,而不是回溯,但這個解決方案也是遞歸的。 – Selcuk 2015-04-05 11:15:29