我有一个像这样的数字列表(随机生成,在每个子组中排序的数字。这些组是不相交的,这意味着你不会在多个组中找到给定的数字):
L=[[19,18,14,9,4],[15,12,11,10,6,5],[8],[16,13,3,2],[17,7,1]]
我正在尝试计算我可以创建递减三元组的方式。
reduce-triplet是三元组,我们从左到右扫描列表并从组中取出元素1,然后从另一个组中取出元素2,然后从另一个组中取出元素3,其中最终结果应按降序排列自然。
例如,(19,11,7)是一个有效的递减三元组,因为这些数字来自不同的子列表,并且是递减的,自然顺序(19在11之前出现在主列表中的7之前)。 / p>
用一个反例来澄清:(15,9,8)不会是一个递减的三元组,因为9来自早于15的子列表。
我正在尝试使用动态编程或某种记忆来计算递减三元组的数量。设置如下的循环结构很容易:
for i in xrange(0,len(L)-2):
for j in xrange(i+1, len(L)-1):
for k in xrange(j+1, len(L)):
for item1 in L[i]:
for item2 in L[j]:
if item1>item2:
for item3 in L[k]:
if item2>item3:
count+=1
但是对于较大的列表,它不能很好地扩展。我觉得应该有一些方法可以通过列表一次计算三胞胎。例如,如果我知道一个数字大于另一个数字(或者如果我知道它的数量大于多少),我觉得我应该能够在以后重新使用这些信息。
例如,我知道16可以在7或1之前出现在有效的三元组中。那是2对“。”因此,如果我想在列表中向后移动时创建一个三元组,我看一下,比方说,19,我应该可以说“它大于16,因此你可以创建两个三元组,因为我们知道16大于2个数字。“等等。
我只是在大声思考,但会欣赏一些见解。
答案 0 :(得分:0)
尝试以下itertool解决方案
import itertools
import time
L= [
{19, 18, 14, 9, 4},
{15, 12, 11, 10, 6, 5},
{8},
{16, 13, 3, 2},
{17, 7, 1},
]
start = time.time()
for i in xrange(20000):
count = 0
for i in xrange(0,len(L)-2):
for j in xrange(i+1, len(L)-1):
for k in xrange(j+1, len(L)):
for item1 in L[i]:
for item2 in L[j]:
if item1>item2:
for item3 in L[k]:
if item2>item3:
count+=1
print
print time.time() - start
# result: 3.1542930603
start = time.time()
for i in xrange(20000):
sum(1 for l1, l2, l3 in itertools.combinations(L, 3) for a, b, c in itertools.product(l1, l2, l3) if a > b > c)
print
print time.time() - start
# result: 1.94973897934
答案 1 :(得分:0)
在i
和0
之间使用索引n
而不是嵌套循环。
跟踪当前三元组的最后一个元素。
并使用备忘录使其高效。
L=[[19,18,14,9,4],[15,12,11,10,6,5],[8],[16,13,3,2],[17,7,1]]
n=len(L)
memo = {}
def f(i,j,last):
if (i,j,last) in memo:
return memo[(i,j,last)]
if j==3:
return 1
if i==n:
return 0
res=0
# take one from L[i]
for x in L[i]:
if last > x:
res+=f(i+1,j+1,x)
# don't take any element from L[i]
res += f(i+1,j,last)
memo[(i,j,last)] = res
return res
BIG = 10**9
print f(0,0,BIG)