过滤子集和组合中的重复项

时间:2017-12-05 03:16:32

标签: python arrays list subset-sum

给定一个数组,我发现子集的所有组合等于目标总和,因为我想要最大的数组。

例如,数组 [1,2,2,2] ,目标总和为" 4"返回 [[2,2],[2,2],[2,2]]

subsets = []

def subset_sum(numbers, target, partial=[]):
    s = sum(partial)
    if s == target:
        subsets.append(partial)
    if s >= target:
        return
    for i in range(len(numbers)):
        n = numbers[i]
        remaining = numbers[i + 1:]
        subset_sum(remaining, target, partial + [n])

subsets.sort()
subsets.reversed()

如何删除子集中曾提到过的值'清单? 在上面的例子中,我怎么能只关注一个[2,2]。

那么,显示初始数组的值不在最终列表中? 在上面的例子中[1]。

3 个答案:

答案 0 :(得分:0)

您可以使用itertools.groupby删除重复的列表:

>>> import itertools
>>> lst = [[2, 2], [2, 2], [2, 2]]
>>> lst.sort()
>>> new_lst = list(k for k,_ in itertools.groupby(lst))
>>> print(new_lst)
[[2, 2]]

然后简单地用itertools.chain.from_iterable展平new_lst,并检查此展平列表中是否存在初始列表中的任何元素:

>>> initial = [1,2,2,2]
>>> print([x for x in initial if x not in itertools.chain.from_iterable(new_lst)])
[1]

注意:您可以让subset_sum()返回非重复项目列表,但上述情况也可以正常工作。

答案 1 :(得分:0)

这不是您问题的直接答案,而是更好的算法。如果您只是查找满足您的总和标准的最大长度列表的一个示例,那么您应首先查看更长的列表。此代码使用itertools作为组合位,并在找到最长列表时停止。

numbers = [1, 2, 2, 2]
taget = 5

for size in reversed(range(1, 1 + len(numbers))):
    for c in itertools.combinations(numbers, size):
        if sum(c) == target:
            break
    else:
        continue
    break

c现在包含最长的子集作为元组(1, 2, 2)

答案 2 :(得分:0)

您可以这样做:

  

数据是:

data=[1, 2, 2,2]
import itertools
your_target=4
  

一线解决方案:

print(set([k for k in itertools.combinations(data,r=2) if sum(k)==your_target]))

输出:

{(2, 2)}

或更好的使用函数:

def targeted_sum(data,your_target):
    result=set([k for k in itertools.combinations(data,r=2) if sum(k)==your_target])
    return result

print(targeted_sum(data,4))