如何找到加起来等于给定总和的索引和组合?

Posted

技术标签:

【中文标题】如何找到加起来等于给定总和的索引和组合?【英文标题】:How to find indices and combinations that adds upto given sum? 【发布时间】:2020-06-12 16:14:47 【问题描述】:

如何找到加到给定 sum 的组合和对应的索引? 另外,是否可以处理大小为 500000(更大)的元素列表?

输入:

l1 = [9,1, 2, 7, 6, 1, 5] 
target = 8

**Constraints**
1<=(len(l1))<=500000
1<=each_list_element<=1000

输出:

Format : index:element
1:1, 5:1, 4:6   #Indices : 1,5,4   Elements : 1,1,6
1:1, 2:2,  6:5
5:1, 2:2,  6:5
1:1,  3:7
5:1,  3:7
2:2,  4:6

试过了:

from itertools import combinations

def test(l1, target):
    l2 = []
    l3 = []    
    if len(l1) > 0:
        for r in range(0,len(l1)+1):        
            l2 += list(combinations(l1, r))

        for i in l2:        
            if sum(i) == target:
                l3.append(i)

    return l3

l1 = [9,1, 2, 7, 6, 1, 5] 
target = 8
print(test(l1,target))

[(1, 7), (2, 6), (7, 1), (1, 2, 5), (1, 6, 1), (2, 1, 5)]

有人可以指导我吗?

更新

Apart from above, code fails to handle these scenarios
Input = [4,6,8,5,3]
target = 3

Outputs  , need to output 4:3

Input = [4,6,8,3,5,3]
target = 3

Outputs  , need to output 5:3,3:3   #corrected index

Input = [1,2,3,15]
target = 15

Outputs = , need to output 3:15

【问题讨论】:

您的代码在哪里显示您为解决问题所做的努力或代码中任何不起作用的问题。我建议查看诸如组合之类的功能的 itertools 模块之类的东西 @ChrisDoyle:发布了上面的解决方案,我试过了。我无法在这里跟踪相应的索引。有更好的方法吗?保持性能、执行时间和处理更多列表中的元素。 @Chris Doyle:有什么想法吗? l1 中的数字总是唯一的吗?您可以通过忽略所有大于目标的数字来减少组合的数量。我会使用 enumerate 来生成索引、值元组,然后从中进行组合。 @Chris Doyle:有时可能是独一无二的,但也存在重复元素。在这种情况下,我们需要考虑它们。输入=[1,6,7,1,3],目标=5,输出=0:1,3:1,4:3,0:1,0:1,4:3,3 :1,3:1,4:3。我应该为此创建单独的问题吗? 【参考方案1】:

您的代码很接近,我会使用 enumerate 将索引和值作为元组对获取。我总是删除任何值大于目标的索引和值元组,因为这不可能是匹配的。这将产生更少的组合。然后像你一样,我只是遍历元组的排列并对每个排列中的值求和,如果它总和为目标,则产生该排列。最后在循环中输出我给 dict 的值以转换成你想要的 dict 格式

from itertools import combinations


def find_sum_with_index(l1, target):
    index_vals = [iv for iv in enumerate(l1) if iv[1] < target]
    for r in range(1, len(index_vals) + 1):
        for perm in combinations(index_vals, r):
            if sum([p[1] for p in perm]) == target:
                yield perm


l1 = [9, 1, 2, 7, 6, 1, 5]
target = 8
for match in find_sum_with_index(l1, target):
    print(dict(match))

输出

1: 1, 3: 7
2: 2, 4: 6
3: 7, 5: 1
1: 1, 2: 2, 6: 5
1: 1, 4: 6, 5: 1
2: 2, 5: 1, 6: 5

【讨论】:

有趣。看起来不错,但无法处理一些场景,在 UPDATE 部分使用场景更新问题。 您真的不知道我的代码中需要更新哪些内容才能使其适用于您的新示例? 只需将if iv[1] &lt; target 更改为if iv[1] &lt;= target,因为我只保留小于目标的数字,因为我假设您只想找到总和为目标的数字,我没有考虑单个匹配目标的实例组合 很好,没错。抱歉,我没有注意到这一点。谢谢克里斯。 正在考虑另一种情况。如果输入=[9,6,8,1,7],目标=5,输出=3:1,3:1,3:1,3:1,3:1,3:1。因为,1 可以添加 5 次以使其成为目标。【参考方案2】:

您可以只使用索引函数获取索引并将它们存储为键:值对,在另一个列表中的字典的帮助下,如下所示,

from itertools import combinations

def test(l1, target):
    l2 = []
    l3 = []
    l4=[]
    dict1=
    a=0
    if len(l1) > 0:
        for r in range(0,len(l1)+1):        
            l2 += list(combinations(l1, r))

        for i in l2:
            dict1=
            if sum(i) == target:

                for j in i:
                    a=l1.index(j)
                    dict1[a]=j
                l4.append(dict1)
                l3.append(i)

    return l4

l1 = [4,6,8,5,3]
target = 3

print(test(l1,target))

输出:

[4: 3]

如您所见,l1 = [4,6,8,5,3] target = 3 的条件有效,而以前无效。

希望这会有所帮助!

【讨论】:

Input = [4,6,8,3,5,3] , target=3, 它打印 [3: 3, 3: 3] 而不是 5:3, 3:3。而且,它应该是一个字典,由这些组合组成。 这是有多个相同值的问题,因为我使用了 index() 方法,它返回该值第一次出现的索引。

以上是关于如何找到加起来等于给定总和的索引和组合?的主要内容,如果未能解决你的问题,请参考以下文章

获取加起来等于给定数字的所有可能总和

c_cpp 给定二叉树和求和,找到所有根到叶路径,其中每个路径的总和等于给定的总和

回溯 - 给定一组数字,找到总和等于 M 的所有子集(给定 M)

查找等于给定总和的数组元素[关闭]

如何从数组中找到3个数字的组合,当添加时,它等于另一个给定的数字

Leetcode练习(Python):树类:第113题: 路径总和 II:给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。 说明: 叶子节点是指没有子节点的节点。