Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python列表的累积和大于列表中的其余元素_Python_Algorithm_List - Fatal编程技术网

Python列表的累积和大于列表中的其余元素

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。列表可能有数百万个元素。 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
        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