我正在使用python2.7,我需要构建followind数据结构: 它必须存储所有三元组,使得:x< y< z< N(给出N)。 我可以随机选择一个三胞胎。 我有一个" Pop"带有输入的函数,如果它存在或从中返回" False"如果它不在数据库中。
N可能非常大。
我的代码:
N = 1000
Root = []
for x in range(0,N-2):
xNode = [x, []]
for y in range(x+1,N-1):
yNode = [y, []]
for z in range(y+1,N):
yNode[1].append(z)
xNode[1].append(yNode)
Root.append(xNode)
print "Loading [{0:.2f}%]".format(float(100*x)/(N-2))
在我的电脑上N=1000
有一个MemoryError
。我想要一个数据结构,而不是[]
,它将零件存储到内存中。我不在乎它是否慢,只要它不受N
的限制(至少比{1}}小于我的PC中的光盘空间)
是否有可以使用的模块或其他东西?
答案 0 :(得分:1)
据我了解您的问题,您需要针对该空列表进行解决方法并重复添加。
当我运行你的程序时,在我的本地机器中,N = 4的输出是:
>>> N = 4
>>> Root = []
>>> for x in range(0,N-2):
... xNode = [x, []]
... for y in range(x+1,N-1):
... yNode = [y, []]
... for z in range(y+1,N):
... yNode[1].append(z)
... xNode[1].append(yNode)
... Root.append(xNode)
...
>>> for i in Root:
... print i
...
[0, [[1, [2, 3]], [2, [3]]]]
[1, [[2, [3]]]]
我在这里假设您至少希望输出看起来像这样:
[0, 1, 2]
[0, 1, 3]
[0, 2, 3]
[1, 2, 3]
要实现这一点,您需要对代码进行一些小改动。您可以将每个列表直接附加到最里面的循环中,而不是临时xNode
和yNode
。
>>> N = 4
>>> Root = []
>>> for x in xrange(0, N-2):
... for y in xrange(x+1, N-1):
... for z in xrange(y+1, N):
... Root.append([x, y, z])
...
>>>
现在,对于N = 1000,列表的大致长度为O(N^3)
或大约10^9
,这对本地计算机来说非常大。为了给你一个想法,列表的每个元素由3个整数组成。假设整数的大小为4 bytes
,则列表的每个元素的大小为12 bytes
。将完整列表存储在内存中所需的总内存为12*(10^9) bytes
,大约为11 GB
。
关于检查和弹出元素的主要问题,您可以按如下方式执行:
我们的想法是假设所有有效的三元组最初都存在于内存中(虽然我们不会存储它,因为你提到N
可能非常大而且我们无法存储所有三元组以获得更大的值N
)。我们将制作三个N
大小的列表 - x
,y
和z
。每当我们弹出三元组时,我们都会在这些列表中标记相应的值。稍后,如果我们遇到相同的三元组,那么我们可以在O(1)
时间检查它是否已被弹出。空间复杂度为O(N)
,时间复杂度为O(queries)
。
N = int(raw_input())
# number of queries
queries = int(raw_input())
x = [0]*N
y = [0]*N
z = [0]*N
for i in xrange(queries):
a, b, c = map(int, raw_input().split())
if a < b and b < c and c < N:
# Basic idea is if (x[a], x[b], x[c]) = (1, 1, 1), then it has already
# popped off, else, we pop it and mark it as popped.
if x[a] == 1 and x[b] == 1 and x[c] == 1:
print 'Triplet not in memory to remove'
else:
x[a] = 1
x[b] = 1
x[c] = 1
print 'Triplet (%d, %d, %d) popped off memory' % (a, b, c)