我需要制作一个有效的算法,从一个列表中获取所有可能的元素(EDIT:pairwise)(包括它们自己),并将它们存储到另一个列表中,直到某个值。
例如,如果值为30,列表为[1,2,3,4,5,15,20]
,我想要一个列表:
[1,2,3,4,5,6,7,8,9,10,15,16,17,18,19,20,21,22,23,24,25,30]
现在我有一个有效的算法,但效果极差(我需要做到29000:
sumlist = [0]*60000
for j in range(0,len(abundlist)):
for i in range(j,len(abundlist)):
if sumlist[abundlist[i] + abundlist[j]] == 0: sumlist[abundlist[i] + abundlist[j]] = 1
如果总和发生了,我把1放在哪里,以避免相等的值。 我还试图首先消除丰富列表中的所有倍数,但这根本没有帮助。
我想我可能正在接近这个问题。任何建议/优化/评论都会非常有帮助。
答案 0 :(得分:1)
您不需要使用第一行在python中初始化列表。使用列表理解来总结每个数字的位数:
>>> x=[1,2,3,4,5,15,20]
>>> [i+j for i in x for j in x]
[2, 3, 4, 5, 6, 16, 21, 3, 4, 5, 6, 7, 17, 22, 4, 5, 6, 7, 8, 18, 23, 5, 6, 7, 8, 9, 19, 24, 6, 7, 8, 9, 10, 20, 25, 16, 17, 18, 19, 20, 30, 35, 21, 22, 23, 24, 25, 35, 40]
如果你想限制它,你可以在理解的末尾添加一个简单的过滤器:
>>> [i+j for i in x for j in x if i+j<=30]
[2, 3, 4, 5, 6, 16, 21, 3, 4, 5, 6, 7, 17, 22, 4, 5, 6, 7, 8, 18, 23, 5, 6, 7, 8, 9, 19, 24, 6, 7, 8, 9, 10, 20, 25, 16, 17, 18, 19, 20, 30, 21, 22, 23, 24, 25]
如果他们需要是唯一的,你可以把它变成一个集合,然后再回到列表:
>>> list(set([i+j for i in x for j in x if i+j<=30]))
[2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 30]
但是,集合未排序,并且转换回列表可能无法保持顺序,因此您也可以对其进行排序:
>>> sorted(list(set([i+j for i in x for j in x if i+j<=30])))
[2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 30]
这是一个有趣的小测试,显示执行质量总和,包括多次向集合和列表进行转换。从本质上讲,它构建了一个从1到1000的数字列表(向较小的数字加权以匹配原始问题中的数字),然后执行如上所述的总和。
构建和运行列表,并对其进行求和,100次不到2秒。
>>> timeit.timeit(
'x=sorted(list(set([randint(1,i) for i in range(2,1000)])));z=[i+j for i in x for j in x if i+j<=500]',
setup="from random import randint",number=100)
1.7806868553161621