简体   繁体   English

查找所有总计为给定数字的可能子集

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

I'm learning Python and I have a problem with this seems to be simple task. 我正在学习Python,对此问题似乎很简单。

I want to find all possible combination of numbers that sum up to a given number. 我想找到所有总计给定数字的可能组合。
for example: 4 -> [1,1,1,1] [1,1,2] [2,2] [1,3] 例如:4-> [1,1,1,1] [1,1,2] [2,2] [1,3]

I pick the solution which generate all possible subsets (2^n) and then yield just those that sum is equal to the number. 我选择生成所有可能的子集(2 ^ n)的解决方案,然后得出总和等于数字的那些子集。 I have a problem with the condition. 我的状况有问题。 Code: 码:

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 is it a good approach? BTW是个好方法吗?

Here's some code I saw a few years ago that does the trick: 这是几年前我看到的一些实现此目的的代码:

>>> 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]]

Additional References: 其他参考文献:

That solution doesn't work, right? 该解决方案不起作用,对吗? It will never add a number to a subset more than once, so you will never get, for example, [1,1,2]. 它永远不会将一个数字加到子集上一次,因此您将永远不会得到例如[1,1,2]。 It will never skip a number, either, so you will never get, for example, [1,3]. 它也永远不会跳过数字,因此您永远也不会得到例如[1,3]。

So the problem with your solution is twofold: One, you are not actually generating all possible subsets in the range 1..number. 因此,解决方案存在两个问题:第一,实际上并没有生成1..number范围内的所有可能子集。 Two, The set of all subsets will exclude things that you should be including, because it will not allow a number to appear more than once. 第二,所有子集的集合将排除您应包括的内容,因为它不允许数字出现多次。

This kind of problem can be generalized as a search problem. 这种问题可以概括为搜索问题。 Imagine that the numbers you want to try are nodes on a tree, and then you can use depth-first search to find all paths through the tree that represent a solution. 想象一下,您想尝试的数字是一棵树上的节点,然后您可以使用深度优先搜索来找到代表该解决方案的所有路径。 It's an infinitely large tree, but luckily, you never need to search all of it. 它是一棵无限大的树,但是幸运的是,您不需要搜索所有的树。

Here is an alternate approach which works by taking a list of all 1s and recursively collapsing it by adding subsequent elements, this should be more efficient than generating all possible subsets: 这是一种替代方法,该方法通过获取全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]]

You can strip off the last value if you don't want the trivial case. 如果您不希望出现这种情况,则可以去除最后一个值。 If you will just be looping over the results remove the list call and just return the generator. 如果您只是要遍历结果,请删除list调用并返回生成器。

This is equivalent to the problem described in this question and can use a similar solution. 这等效于此问题中描述的问题,并且可以使用类似的解决方案。

To elaborate: 详细说明:

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

That translates this question into that question and back again. 这就把这个问题翻译成那个问题,然后又回来了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 递归回溯以列出给定总和的所有子集? - recursive backtracking to list all subsets with a given sum? 一个 function 返回所有可能的子 arrays 总和为特定给定数字(不必是连续子数组) - a function that return all possible sub arrays that sum up to a specific given number (need not to be a continuous sub array) 查找行的索引,其中直到该索引为止的所有行的总和为给定的数字 - Find index of row where all the rows up until that index sum to a given number 在Django中生成给定QuerySet的所有可能子集 - Generating all possible subsets of a given QuerySet in Django 查找一个数字是否是给定集合中两个或更多个数字的可能总和--python - Find if a number is a possible sum of two or more numbers in a given set - python 查找数组中总和为给定值的所有元素对 - Find all pairs of elements within an array that sum up to a given value 具有给定总和的子集数。 递归不跟踪树的几个分支 - Number of subsets with a given sum . Recursion not tracing few branches of the tree 递归程序以获得具有给定总和的所有子集包括重复 - Recursive program to get all subsets with given sum includes repetitions 查找总和最接近给定数字的所有数字 python - Find all numbers that sum closest to a given number python 创建一个递归函数以获取整数列表中所有可能子集的和 - Creating a recursive function that gets the sum of all possible subsets in a list of integers
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM