【发布时间】:2014-02-08 15:43:31
【问题描述】:
我有一个问题,我想计算满足以下条件的组合的数量:
a < b < a+d < c < b+d
其中a, b, c 是列表的元素,d 是固定增量。
这是一个普通的实现:
def count(l, d):
s = 0
for a in l:
for b in l:
for c in l:
if a < b < a + d < c < b + d:
s += 1
return s
这是一个测试:
def testCount():
l = [0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 5, 7, 7, 8, 9, 9, 10, 10]
assert(32 == count(l, 4)) # Gone through everything by hand.
问题
如何加快速度?我正在查看 200 万的列表大小。
补充信息
我正在处理 [-pi, pi] 范围内的浮点数。例如,这限制了a < 0。
到目前为止我所拥有的:
我有一些实现,我在其中构建用于b 和c 的索引。但是,以下代码在某些情况下会失败。 (即这是错误的)。
def count(l, d=pi):
low = lower(l, d)
high = upper(l, d)
s = 0
for indA in range(len(l)):
for indB in range(indA+1, low[indA]+1):
s += low[indB] + 1 - high[indA]
return s
def lower(l, d=pi):
'''Returns ind, s.t l[ind[i]] < l[i] + d and l[ind[i]+1] >= l[i] + d, for all i
Input must be sorted!
'''
ind = []
x = 0
length = len(l)
for elem in l:
while x < length and l[x] < elem + d:
x += 1
if l[x-1] < elem + d:
ind.append(x-1)
else:
assert(x == length)
ind.append(x)
return ind
def upper(l, d=pi):
''' Returns first index where l[i] > l + d'''
ind = []
x = 0
length = len(l)
for elem in l:
while x < length and l[x] <= elem + d:
x += 1
ind.append(x)
return ind
原来的问题
最初的问题来自一个著名的数学/计算机科学竞赛。比赛要求您不要在网上发布解决方案。但那是两周前的事了。
我可以用这个函数生成列表:
def points(n):
x = 1
y = 1
for _ in range(n):
x = (x * 1248) % 32323
y = (y * 8421) % 30103
yield atan2(x - 16161, y - 15051)
def C(n):
angles = points(n)
angles.sort()
return count(angles, pi)
【问题讨论】:
-
列表总是排序的吗?
-
最初没有排序,但我们可以做到。
-
对我来说,这是一项测试:
a < (c - d) < b。因此,首先,您永远不必查看小于或等于a的b。这会大大减少你的比较。 -
因为对于给定范围内的整数,您可以使用段树。你不能用花车做到这一点。一般来说,对于此类问题,请提供您拥有的所有信息。
-
你能链接到问题陈述或简要描述它吗?我认为即使在你给出的一般公式中也可以在多线性时间内解决这个问题,但我认为比赛不需要这样做
标签: python algorithm combinations