对数组的每个元素进行递归

时间:2018-01-31 21:12:14

标签: python arrays list recursion dynamic-programming

我有一个整数S和一个整数集合A.我需要从集合中找到一组整数,其中这些整数的总和等于S.它可以是1整数或50 - 这没关系。

我试图这样做:

我有一个数组res和一个数组grp

res以[0]开头,grp是最初给定的集合,S是我们想要找到的总和,S是全局的

我的功能需要(res,grp)

我想这样做:(和例子)

enter image description here     -

并在res元素之和等于S

时停止

但是我很喜欢递归而且我不知道我应该做什么

这是我的代码

S = 7
grp = [0,5,6,4,3]

def sumFinder(res,grp):
    if grp == []:
        return grp #in case no pair was found [] is returned 
    if sum(res) == S:
        return res
    for i in range (0,len(grp)):
        print(res)
        print(grp[i])
        res += [grp[i]]
        newgrp = grp[:i]
        newgrp += grp[i+1:]
        return sumFinder(res,newgrp)

 print(sumFinder([0],grp))

更新

谢谢大家的答案 谢谢 englealuze 给我一个关于解决问题的好主意,谢谢你我得到了这个:

1 - 这是为了找到第一个组合并返回它(这是我的目标)

grp = [1,0,1,0,1,2,6,2,3,5,6,7,8,9,2,1,1,9,6,7,4,1,2,3,2,2]
S = 55
grps = []

def findCombination(comb,grp):
    for i in range (0,len(grp)):
        comb += [grp[i]]
        newgrp = grp[:i]
        newgrp += grp[i+1:]

        if sum(comb) == S:
            return comb

        if newgrp not in grps:
            grps.append(newgrp)
            res = findCombination([],newgrp)
            if res != None:
                return res

print(findCombination([],grp))

2-这是为了找到所有组合:(这是 englealuze 所讨论的问题,但即使看起来更好,我也不理解他的方法)

grp = [1,0,1,1,9,6,7,4,1,2,3,2,2]
S = 12
grps = []
combinations = []

def findAllCombinations(comb,grp):
    global combinations
    for i in range (0,len(grp)):
        comb += [grp[i]]
        newgrp = grp
        newgrp = grp[:i]
        newgrp += grp[i+1:]

        if sum(comb) == S and tuple(comb) not in combinations:
            combinations.append(tuple(comb))

        if newgrp not in grps:
            grps.append(newgrp)
            findAllCombinations([],newgrp)

findAllCombinations([],grp)
print(combinations)

我现在唯一的问题是当S> 50(在第一个),找到答案需要更长的时间

你们可以给我什么建议来改进这两种算法?

3 个答案:

答案 0 :(得分:3)

以下代码工作(删除'直接返回'在循环中,更改为有条件的'返回')。

但我不认为这是一个很好的解决方案。你需要改进你的算法。

PS:此代码也只返回一个匹配而不是全部。

S = 7
grp = [0,3,6,4,6]

result = []

def sumFinder(res,grp, result):
    for i in range (0,len(grp)):
        temp = list(res) #clone res instead of direct-reference
        if grp == [] or not temp:
            return grp #in case no pair was found [] is returned
        if sum(temp) == S:
            result.append(tuple(temp))
            return temp
        temp.append(grp[i])
        newgrp = grp[:i] + grp[i+1:]
        sumFinder(list(temp),newgrp, result)

sumFinder([0], grp, result)
print result

测试案例:

S = 7
grp = [0,3,6,4,6]
result = [(0, 0, 3, 4), (0, 0, 4, 3), (0, 3, 0, 4), (0, 3, 4), (0, 4, 0, 3), (0, 4, 3)]
[Finished in 0.823s]

答案 1 :(得分:3)

除了提供代码之外,我将向您展示如何思考此问题以及如何在一般意义上解决此类问题。

首先,让我们重新解释一下你的问题。实际上你想要的是给定一组数字,找到满足一定条件的集合内的组合。因此,您可以将问题分解为两个不同的步骤。

  1. 查找您的所有组合
  2. 过滤掉满足特定条件的组合
  3. 让我们考虑如何递归地解决第一个任务。请记住,如果问题可以以递归方式解决,通常意味着数据中存在一些递归模式,通常可以通过非常简单明了的方式解决。如果你最终得到一个混乱的递归解决方案,它几乎意味着你的方向错误。

    让我们先看看您的数据模式。如果你有一个非常小的集合(1,2),那么这个集合中的组合是

    1
    2
    1, 2
    

    让我们将一个成员增加到集合中,(1,2,3)。对于这个更大的集合,所有组合都是

    1       | 1, 3
    2       | 2, 3
    1, 2    | 1, 2, 3
            | 3
    

    让我们看看更大的集合(1,2,3,4)。可能的组合是

    1       1, 3       | 1, 3, 4
    2       2, 3       | 2, 3, 4
    1, 2    1, 2, 3    | 1, 2, 3, 4
            3          | 3, 4
                       | 4
    

    现在你看到一些有趣的东西,一个较大的集合的组合是较小集合的组合加上附加到每个先前组合的附加元素以及附加元素本身。

    假设您已经获得了具有特定大小的所有组合的解,那么可以从该解决方案中获得更大集合的解。这自然形成递归。您可以将此简单英语直接翻译为递归代码,如下所示

    # assume you have got all combinations of a smaller set -> combinations(smaller(L))
    # the solution of your bigger set can be directly derived from it with known new element
    def combinations(L):
        if L == []:
            return []
        else:
            return next_solution(combinations(smaller(L)), newitem(L))
    

    请注意我们如何将解决较大问题的任务分解为解决较小的问题。您需要如下的帮助函数

    # in your case a smaller set is just the new set drop one element
    def smaller(L):
        return L[1:]
    
    # the new element would be the first element of new set
    define newitem(L):
        return L[0]
    
    # to derive the new solution from previous combinations, you need three parts
    # 1. all the previous combinations -> L
    # 2. new item appending to each previous combination -> [i + [newelement] for i in L]
    # 3. the new item itself [[newelement]]
    def next_solution(L, newelement):
        return L + [i + [newelement] for i in L] + [[newelement]]
    

    现在我们知道如何从一组中获取所有组合。 然后要过滤它们,您不能直接将过滤器插入到递归步骤中,因为我们依赖于先前的解决方案来递归地构建结果列表。简单的方法是在我们获得所有组合的完整结果时过滤列表。

    你最终会得到一个解决方案。

    def smaller(L):
      return L[1:]
    
    def newitem(L):
      return L[0]
    
    def next_solution(L, newelement):
      return L + [i + [newelement] for i in L] + [[newelement]]
    
    def filtersum(L, N, f=sum):
      return list(filter(lambda x: f(x)==N, L))
    
    def combinations(L):
      if L == []:
        return []
      else:
        return next_solution(combinations(smaller(L)), newitem(L))
    
    def filter_combinations(L, N, f=filtersum):
      return f(combinations(L), N)
    
    print(filter_combinations([0,5,6,4,3], 7))
    # -> [[3, 4], [3, 4, 0]]
    

    您可以通过在每次递归调用中过滤掉总和大于您定义值的组合来保存一些计算,例如

    def combinations(L):
      if L == []:
        return []
      else:
        return next_solution(list(filter(lambda x: sum(x) <=5, combinations(smaller(L)))), newitem(L))
    
    print(combinations([1,2,3,4]))
    # -> [[4], [3], [3, 2], [2], [4, 1], [3, 1], [3, 2, 1], [2, 1], [1]]
    

    实际上会有不同的递归方式,取决于将问题分解为较小问题的方式。存在一些更聪明的方法,但我上面展示的方法是解决此类问题的典型和一般方法。

    我有用这种方式解决其他问题的例子

    Python: combinations of map tuples

答案 2 :(得分:2)

你能告诉我你在哪里发现这个问题吗?我喜欢解决这类问题,Bdw这是我的方法:

a=[[[0],[0,5,6,4,3]]]

s=7

def recursive_approach(array_a):
    print(array_a)
    sub=[]
    for mm in array_a:
        array_1 = mm[0]
        array_2 = mm[1]
        if sum(array_2)==s:
            return "result is",array_2
        else:
            track = []
            for i in range(len(array_2)):
                c = array_2[:]
                del c[i]

                track.append([array_1 + [array_2[i]], c])
            sub.append(track)
    print(sub)
    return recursive_approach(sub[0])





print(recursive_approach(a))

输出:

[[[0], [0, 5, 6, 4, 3]]]
[[[[0, 0], [5, 6, 4, 3]], [[0, 5], [0, 6, 4, 3]], [[0, 6], [0, 5, 4, 3]], [[0, 4], [0, 5, 6, 3]], [[0, 3], [0, 5, 6, 4]]]]
[[[0, 0], [5, 6, 4, 3]], [[0, 5], [0, 6, 4, 3]], [[0, 6], [0, 5, 4, 3]], [[0, 4], [0, 5, 6, 3]], [[0, 3], [0, 5, 6, 4]]]
[[[[0, 0, 5], [6, 4, 3]], [[0, 0, 6], [5, 4, 3]], [[0, 0, 4], [5, 6, 3]], [[0, 0, 3], [5, 6, 4]]], [[[0, 5, 0], [6, 4, 3]], [[0, 5, 6], [0, 4, 3]], [[0, 5, 4], [0, 6, 3]], [[0, 5, 3], [0, 6, 4]]], [[[0, 6, 0], [5, 4, 3]], [[0, 6, 5], [0, 4, 3]], [[0, 6, 4], [0, 5, 3]], [[0, 6, 3], [0, 5, 4]]], [[[0, 4, 0], [5, 6, 3]], [[0, 4, 5], [0, 6, 3]], [[0, 4, 6], [0, 5, 3]], [[0, 4, 3], [0, 5, 6]]], [[[0, 3, 0], [5, 6, 4]], [[0, 3, 5], [0, 6, 4]], [[0, 3, 6], [0, 5, 4]], [[0, 3, 4], [0, 5, 6]]]]
[[[0, 0, 5], [6, 4, 3]], [[0, 0, 6], [5, 4, 3]], [[0, 0, 4], [5, 6, 3]], [[0, 0, 3], [5, 6, 4]]]
[[[[0, 0, 5, 6], [4, 3]], [[0, 0, 5, 4], [6, 3]], [[0, 0, 5, 3], [6, 4]]], [[[0, 0, 6, 5], [4, 3]], [[0, 0, 6, 4], [5, 3]], [[0, 0, 6, 3], [5, 4]]], [[[0, 0, 4, 5], [6, 3]], [[0, 0, 4, 6], [5, 3]], [[0, 0, 4, 3], [5, 6]]], [[[0, 0, 3, 5], [6, 4]], [[0, 0, 3, 6], [5, 4]], [[0, 0, 3, 4], [5, 6]]]]
[[[0, 0, 5, 6], [4, 3]], [[0, 0, 5, 4], [6, 3]], [[0, 0, 5, 3], [6, 4]]]
('result is', [4, 3])