sum() 是否在 python3 中占用循环的执行时间

does sum() take the execution time of a loop in python3

我在循环中使用了sum(),执行时间超过4s,这里的sum()等于嵌套循环吗?

def arrayMaxConsecutiveSum(inputArray, k):
    cop=k
    lis=[]
    i=0
    while i < len(inputArray):
        inpu=sum(inputArray[i:cop])
        lis.append(inpu)
        cop+=1
        i+=1
    return max(lis)

sum 是作为 C++ 库实现的,因此它仍然比 Python for 循环更快,尽管您仍然是 运行 嵌套循环.为了说明,我在这里为您的代码计时,以及使用 Python 循环代替的修改代码:

def arrayMaxConsecutiveSumLoop(inputArray, k):
    cop=k
    lis=[]
    i=0
    while i < len(inputArray) - k:
        inpu = 0
        for j in range(i, cop):  # for-loop in place of sum
            inpu += inputArray[j]
        lis.append(inpu)
        cop += 1
        i += 1
    return max(lis)

时间是:

arrayMaxConsecutiveSum(np.random.rand(10000), 100)
111 ms ± 1.42 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

arrayMaxConsecutiveSumLoop(np.random.rand(10000), 100)
198 ms ± 4.16 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

因此 sum(您的版本)的实施速度大约快两倍!

更好的实施

我使用 numpy 重写了您的函数,使其 更快!此实现没有嵌套循环并且是 O(n),并且使用非常快的 numpy 库实现。

import numpy as np
def array_max_consecutive_sum(input_array, k):
    result = np.cumsum(input_array)
    return max(result[k:] - result[:-k])

array_max_consecutive_sum(np.random.rand(10000), 100)
688 µs ± 10.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

快了 150 多倍!

其他选项

顺便说一句,接受的答案(截至撰写本文时)给出了时间:

6.46 ms ± 147 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

快,但仍然只有上述 numpy 实现的十分之一。还有,结果是错误的。

是的,为了将所有元素加在一起,sum 代码必须遍历 inputArray(从 i 到 cop)。

此外,len(inputArray)还必须遍历整个数组才能得到它的长度。因此,您的解决方案是 O(n*k)

您可以使用以下方法将代码优化为复杂度为 O(n) 的解决方案:

def arrayMaxConsecutiveSum(inputArray, k):
    max = sum(inputArray[0:k])
    bucket = max
    count = len(inputArray)
    for i in range(1, 1 + count - k):
        prev = inputArray[i - 1]
        cur = inputArray[i + k - 1]
        bucket += cur - prev
        if bucket > max:
            max = bucket
    return max

这个算法只在数组上循环一次。想象一下,有一个固定的桶沿着一条线滑动。当您增加 i 时,桶需要取出最新的项目,但最旧的项目会从后面掉下来。使用此逻辑,您最多只需要查看每个项目两次 - 当您将其添加到存储桶中时,以及当您将其从另一端移除时。

** 请注意,为清楚起见,省略了特殊情况处理**