我有一个列表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])
答案 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
构造函数的开销(不确定是否可以绕过后者)