Python列表的累积和大于列表中的其余元素
我想写一个函数,它将返回最小的数字,其中的总和大于列表的其余部分。列表将仅包含值-1和1。列表可能有数百万个元素。 e、 g v=[11-11-11-11] 这里的答案应该是2,因为Python列表的累积和大于列表中的其余元素,python,algorithm,list,Python,Algorithm,List,我想写一个函数,它将返回最小的数字,其中的总和大于列表的其余部分。列表将仅包含值-1和1。列表可能有数百万个元素。 e、 g v=[11-11-11-11] 这里的答案应该是2,因为 1) 1 > 1 is False 2) (1 + 1) 2 > 0 (-1 + 1 -1 +1 -1 +1) 再举一个例子 v=[-1-1] 答复4 我已经试过的代码: def cumsum_grt(v): for i in range(1, len(v)): k = i
1) 1 > 1 is False
2) (1 + 1) 2 > 0 (-1 + 1 -1 +1 -1 +1)
再举一个例子
v=[-1-1]
答复4
我已经试过的代码:
def cumsum_grt(v):
for i in range(1, len(v)):
k = i
if sum(v[:k]) > sum(v[k:]):
break
return k
这个函数可以正常工作,但是有什么方法可以提高性能吗?由于无法在几秒钟内计算大列表的结果,因此失败。这是线性的,O(N),而您的版本类似于O(N*N):
测试:
lst = [1, 1, -1, 1, -1, 1, -1, 1]
lst2 = [1, 1, -1, 20, -1, 15, -1, 1]
lst3 = [-2, -1, 4, -1]
lst4 = [-1,-1,-1,-1]
print(cumsum_grt(lst)) # 2
print(cumsum_grt(lst2)) # 4
print(cumsum_grt(lst3)) # 3
print(cumsum_grt(lst4)) # 1
时间性能测量:
In [101]: lst = [1, 1, -1, 20, -1, 15, -1, 5, -1, -2, 40]
In [102]: %timeit cumsum_grt(lst)
70.3 µs ± 175 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [103]: %timeit cumsum_grt_lenik(lst)
8.23 µs ± 27.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [104]: %timeit cumsum_grt_roman(lst)
8.22 µs ± 30.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
您可以将
next
与itertools.accumulate
一起使用,将当前累积的总和与总和减去累积的总和进行比较,然后使用enumerate
获得该位置的索引<代码>链与列表第一个元素之前的位置的[0]
>>> from itertools import accumulate, chain
>>> v = [1, 1, -1, 1, -1, 1, -1, 1]
>>> s = sum(v)
>>> next((i for i, a in enumerate(chain([0], accumulate(v))) if a > s - a), len(v))
2
注意:不要在
if
条件下计算和(v)
,否则它将是O(n²)。最后的len(v)
是默认值,以防累计总和不足以容纳任何元素。您可能应该以累积的方式计算累计总和。不回答问题,但不需要k
。在python
中,i
的值在循环结束后继续存在,因此您可以在使用k
的任何地方使用i
。为什么我的问题被标记为否定?@BhaveshGhodasara[-1,-1,-1]
的预期结果是什么?我写的代码会返回1
,因为0
大于-4
@RomanPerekhrest同位语,我忽略了这一点..是的,答案应该是1。你不需要从总和中减去一些东西吗?v=列表(np.random.choice([-1,1],size=30000))我用这个列表测试过。用lenik的函数测试你的函数。Lenik的函数用了2.99毫秒,你的函数用了5.98毫秒,而我的函数用了10.6毫秒second@BhaveshGhodasara,我不同意你的时间安排,请看我的更新,我的方法比@lenik的方法慢2倍。他们在时间上很接近,他的方法可能会稍微快一点(OP说答案应该是2
?,我正在测试这个解决方案的时间。我会在测试了这里给出的所有解决方案后接受它的答案。我正在测试这个解决方案的时间。在测试这里给出的所有解决方案后,我将接受它的答案。对于输入[-1,-1,-1,-1]
,这个函数不应该返回1
作为“最小数,其总和大于列表的其余部分吗?”?第一个数字-1
大于剩余的-3
。但是它返回0
@lenik:非常感谢。我现在将试着理解逻辑:)@BhaveshGhodasara逻辑非常简单,列表有两个部分,开始部分和剩余部分。这和你做的差不多,只是,我不是每次都计算这些部分的总和,我只是加/减当前元素以保持它们的更新,这使事情变得更快。@lenik是的,我知道了。我的问题现在听起来很愚蠢:)。
In [101]: lst = [1, 1, -1, 20, -1, 15, -1, 5, -1, -2, 40]
In [102]: %timeit cumsum_grt(lst)
70.3 µs ± 175 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [103]: %timeit cumsum_grt_lenik(lst)
8.23 µs ± 27.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [104]: %timeit cumsum_grt_roman(lst)
8.22 µs ± 30.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
>>> from itertools import accumulate, chain
>>> v = [1, 1, -1, 1, -1, 1, -1, 1]
>>> s = sum(v)
>>> next((i for i, a in enumerate(chain([0], accumulate(v))) if a > s - a), len(v))
2