通过添加数组元素获得数字

时间:2018-09-01 19:16:46

标签: python python-3.x algorithm recursion

因此,我一直试图绕过递归,遇到了这个问题并陷入困境。 在这里...

我已经获得了一个元素数组和一个正整数,我必须找到通过添加array元素(仅使用每个元素一次)来获得正整数的方法的数量。

例如:

array = [1, 4, 9]
n = 10

所以答案将是1,即(1,9)

由于我已经很难理解递归了,请尝试阐述一下

这是我在解决问题时想到的,我也尝试使用循环来完成,但是也没有成功。

def _Sum(X, li):
    if X == 0:
        return 1
    if X < 0:
        return 0
    if X > 0:
        ways = 0
        for i in range(len(li)):
            ways += _Sum(X-li[i], li)
        return ways

4 个答案:

答案 0 :(得分:1)

由于您没有显示任何代码,因此我只是给您一个提示。如果您需要更多细节,请显示更多工作。我将忽略[0](有一种或两种方式?)和n == 0(有空总和吗?)的歧义情况。

如果array为空,则如果1为零,则答案为n,否则为0

如果array有多个元素,则求和array的子数组以得到值n的方法的数量等于求和a的方法的数量。 array[1:]的子数组以获得值n(表示我们不使用总和中的array[0]的值)加上求和{ {1}}来获得array[1:]的值(这意味着我们确实在总和中使用了n - array[0]的值)。


现在您已经显示了自己的代码,这是一个解决问题的例程。这确实将array[0]返回为_Sum(0, [1]),因为它将空总和计为求和为零的方式。如果您不喜欢这样做,请编写一个禁止0为零的外部例程,然后调用我的例程。

有些例程可以避免递归,并且效率更高。还可以修改此例程以避免使用输入列表的一部分,以提高效率,但是编写的例程很简单。

X

为详细说明,请注意我的例程具有一个“基本案例”,该案例检查最简单的可能性。在这里,这意味着检查空白列表。如果特定调用不是基本情况,则我的代码将问题减少为一个或多个较小的问题。在这里,这意味着删除列表的第一个元素。在您的问题中,有两种方法可以获取总和以获取目标值:包括第一个列表值或将其忽略。因此,我们递归调用例程两次,并将两个结果相加。清楚吗?


最后,您问代码有什么问题。简而言之,您的算法是错误的。我不清楚您为什么认为该算法会起作用。基本上,您会不断从目标值中减去其中一个元素,直到它不再为正为止;如果该目标值恰好为零,则您要对方法数加1。但是,如果您看一下示例

def _Sum(X, li):
    """Return the number of sub-lists of list `li` that sum to `X`.
    This assumes list `li` has only positive integers.
    """
    if len(li) == 0:
        if X == 0:
            return 1
        else:
            return 0
    else:
        return _Sum(X, li[1:]) + _Sum(X - li[0], li[1:])

您的代码反复从print(_Sum(2, [1, 2]) 中减去第一个值1直到达到零,然后从2中减去第二个值2直到迅速达到零。这算作两种方式。

像我这样的工作算法需要同时更改目标值和列表,而不仅仅是目标值。您没有这样做,所以失败了。

答案 1 :(得分:0)

解决方案可能会根据预期的时间复杂度而有所不同。如果您只是想使其发挥作用(强力),我将给您一个提示。对于每个元素,您可以选择总和或忽略它。因此,您有2 ^ n种可能性。现在,您只需要以某种方式生成所有这些文件即可。您可以使用递归来实现。避免计数相同的东西是非常困难的。因此,让我们尝试使递归函数选择我们将要使用的第一个元素。然后,再次运行它,但使其选择的元素严格位于第一个元素之后,依此类推。看起来应该像这样:

Fun(prev, sum, value, array)
        if(sum == value)
             ++result
        for i from prev + 1 to size(array)
              Fun(i, sum + array[i], value, array)

答案 2 :(得分:0)

我将创建数组项的每个组合并进行检查。

import itertools

def combinations(lst_items):
    Combinations = []
    for item in map(list, itertools.product([0, 1], repeat=len(lst_items))):
        cCombo = [lst_items[index] for index,i in enumerate(item) if i == 1]
        Combinations.append(cCombo)
    return Combinations

def combo_matches(array, target):
    return [i for i in combinations(array) if sum(i) == target]

combo_matches([1,4,9],10)
[[1, 9]]

combo_matches([1,2,3,4,5,6,7,8,9,10],15)
[[7, 8],
 [6, 9],
 [5, 10],
 [4, 5, 6],
 [3, 5, 7],
 [3, 4, 8],
 [2, 6, 7],
 [2, 5, 8],
 [2, 4, 9],
 [2, 3, 10],
 [2, 3, 4, 6],
 [1, 6, 8],
 [1, 5, 9],
 [1, 4, 10],
 [1, 3, 5, 6],
 [1, 3, 4, 7],
 [1, 2, 5, 7],
 [1, 2, 4, 8],
 [1, 2, 3, 9],
 [1, 2, 3, 4, 5]]

答案 3 :(得分:0)

先前的答案是正确的,这是做同一件事的另一种方法,除了它不使用蛮力并且只对两个数字进行校验

#!/usr/local/bin/python

def sumsToTarget(arr, k):
    arr.sort()
    lhs = 0
    rhs = len(arr)-1
    while lhs < rhs:
        sum = arr[lhs] + arr[rhs]
        if sum == k:
            print'sum of',arr[lhs],'and',arr[rhs],'is',sum
            lhs += 1
        elif sum < k:
            lhs += 1
        else:
            rhs -= 1

arr = [8,6,5,2,4,1,9]
k = 10
sumsToTarget (arr,k)

enter image description here