如何在列表中查找成对的和?

时间:2019-04-26 19:03:31

标签: python sum

我有一个列表x

[1, 2, 3, 3, 5, 5, 6, 7, 8, 9, 9]

并且我想找到所有等于10的货币对

,并且应该是不同的数字对:

{(1, 9), (2, 8), (3, 7), (5, 5)}.

这里是想法,但我对下面的嵌套循环不满意:

def test(x, n):
   pair = set()
   for i in range(len(x)):
        for j in range(len(x)):
            if i !=j:
               pair.add((x[i],x[j])

7 个答案:

答案 0 :(得分:2)

@ThierryLathuille的解决方案假定该列表已预先排序。如果该假设为假,则对列表进行排序将花费 O(n log n)。相反,您可以使用collections.Counter来实现 O(n)时间复杂度,同时考虑列表中每个值的可用项数:

from collections import Counter
counts = Counter(x)
list({frozenset((10 - n, n)): (10 - n, n) for n in counts if counts[10 - n] > (n == 10 - n)}.values())

这将返回:

[(1, 9), (2, 8), (3, 7), (5, 5)]

答案 1 :(得分:1)

如果我们知道想要的总数,我们可以提出问题-对于每个数字,列表中的(总数-数字)是吗?

我们可以将列表变成一组以使用哈希查找:

x = [1, 2, 3, 3, 5, 5, 5, 6, 6, 7, 8, 9, 9]

out = []
total = 10
for i in set(x):
    if (total - i) in set(x) and i < (total+1)/2:
        out.append((i, 10-i))
out

[(1, 9), (2, 8), (3, 7), (5, 5)]

答案 2 :(得分:1)

O(n)中的一种解决方案,用于处理值的排序列表:

values = [1, 2, 3, 3, 5, 5, 6, 7, 8, 9, 9]
target = 10

i = 0
j = len(values) - 1
solutions = set()

while j > i:
    if values[i] + values[j] < target:
        i += 1
    elif values[i] + values[j] > target:
        j -= 1
    else:
        solutions.add((values[i], values[j]))
        i += 1
        j -= 1

print(solutions)
# {(2, 8), (5, 5), (1, 9), (3, 7)}

答案 3 :(得分:1)

这样的事情怎么样

x=[1, 2, 3, 3, 5, 5, 6, 7, 8, 9, 9]
y=[]
for i in x[:5]:
    q=10-i 
    w=(i,q)
    if ((q in x) & (not(w in y))):
        y.append(w)

这可能不是替换您的有效代码,我的观点只是嵌套循环的替代方法

答案 4 :(得分:1)

列表理解将在这里很好地工作。试试这个:

from itertools import permutations

x = [1, 2, 3, 3, 5, 5, 5, 6, 6, 7, 8, 9, 9]
target_number = 10

solutions = [pair for pair in permutations(x, 2) if sum(pair) == 10]
print('Solutions:', solutions)

输出:

Solutions: [(1, 9), (1, 9), (2, 8), (3, 7), (3, 7), (5, 5), (5, 5), (5, 5), (5, 5), (5, 5), (5, 5), (7, 3), (7, 3), (8, 2), (9, 1), (9, 1)]

基本上,此列表推导会查看permutations(x, 2)返回的所有对,但仅保留总和等于10的对。

答案 5 :(得分:0)

您还可以使用一组存储不同值的O(n)解决方案。但是,您需要考虑偶数个目标。即使目标在列表中也需要两个其一半值的实例,但是当列表中实际上只有一个实例时(例如,目标值中的target = 12),该集合将不会进行区分,并且可以找到一对相等的值。

values = [1, 2, 3, 3, 5, 5, 6, 7, 8, 9, 9]
target = 10

valueSet  = set(values)
halfValue = target//2
if 2*halfValue == target and values.count(halfValue) < 2: halfValue -= 1
result   = [ (v,target-v) for v in valueSet if v <= halfValue and target-v in valueSet ]

答案 6 :(得分:0)

单线,不是最有效的:

import itertools

res = set([pair for pair in itertools.combinations(x, 2) if sum(pair)==10])

# {(2, 8), (5, 5), (9, 1), (3, 7)}

您要为在此处生成额外的组合而付出额外的费用,以及set构造函数的开销(不确定是否可以绕过后者)