如何减少python列表算法中k个连续数最大和的执行时间
我的问题是找到给定列表中k个连续数的最大和。 例如: l=[2,3,5,1,6]那么对于k=2,结果将是8(3+5)。 我知道一个好的算法是首先找到前k个数字的和,然后将下一个元素加到和中,然后减去k个数字的第一个元素:如何减少python列表算法中k个连续数最大和的执行时间,python,algorithm,Python,Algorithm,我的问题是找到给定列表中k个连续数的最大和。 例如: l=[2,3,5,1,6]那么对于k=2,结果将是8(3+5)。 我知道一个好的算法是首先找到前k个数字的和,然后将下一个元素加到和中,然后减去k个数字的第一个元素: 2+3 => 5 5-2+5 => 8 ... 我想到了这个: def f(l, k): M= 0 temp = sum(l[0:k]) for i in range(1,k): temp += a[l+1]-l[i-1]
2+3 => 5
5-2+5 => 8
...
我想到了这个:
def f(l, k):
M= 0
temp = sum(l[0:k])
for i in range(1,k):
temp += a[l+1]-l[i-1]
if temp > M:
M = temp
return M
但不幸的是,它只适用于k=2?
因此,我有两个问题:
为此,我们应该使用动态规划,并在
O(n)
复杂度中这样做
from random import randint
test=[randint(1,10) for i in range(5)]
# find cumulative sum use np.cumsum or write is yourself
print(test)
cumsum=[0]*(len(test)+1)
cumsum[1]=test[0]
for i in range(2,len(test)+1):
cumsum[i]=cumsum[i-1]+test[i-1]
print(cumsum)
#define k
k=3
# m denotes the maximum element
m=0
for i in range(len(test)-k+1):
m=max(m,cumsum[k+i]-cumsum[i])
print(cumsum[k+i]-cumsum[i])
# the answer is printed
print(m)
输入
[10, 5, 1, 1, 7]
k=3
输出
16
这真的不是我的专长,但是将列表压缩在一起不是很有效吗 类似于:
from itertools import islice
l = [2,3,5,1,6]
def max_consecutive(ar, k=2):
combos = zip(*(islice(ar,i,None) for i in range(k)))
return max(map(sum, combos))
print(max_consecutive(l))
print(max_consecutive(l, k=3))
返回
8
和12
您描述的想法是正确的,但您的实现是错误的
M
相当于下面的cumax
。应该是
初始化为前k项的总和,而不是0temp
相当于cusum
。行temp+=a[l+1]-l[i-1]
错误。我不知道你从哪里得到的a
。我
你的意思是temp+=l[i+k]-l[i-1]
def f(l, k):
assert len(l) >= k
# Start of max sum of k consecutive number
start_idx = 0
# Current max sum of k consecutive number
cumax = cusum = sum(l[:k])
# Slide a window of size k from second element onwards
N = len(l)
for i in range(1, N - k + 1):
# Subtract element before start of window and add rightmost element
cusum = cusum + l[i + k - 1] - l[i - 1]
# Update start of and latest max sum of k consecutive number if
# necessary
if cusum > cumax:
cumax = cusum
start_idx = i
return start_idx, cumax
def f_convolve(l, k):
start_idx = np.argmax(np.convolve(l, np.ones(k,), 'valid'))
return start_idx, np.sum(l[start_idx : start_idx + k])
如果您有空闲的内存,并且l
不太大,那么此实现的效果甚至比前两个更好
def f_numpy_cusum(l, k):
cumsums = np.cumsum(l)
cumsums[k :] -= cumsums[: len(cumsums) - k ]
cumsums = cumsums[ k- 1:]
start = np.argmax(cumsums)
return start, np.sum(l[start : start + k])
上述3个函数在len(l)
=100000和k
=2000时的运行时间为
f
每个回路32.6 ms+-78.5 us(平均+-7次运行的标准偏差,每个回路10次)
f_卷积
26.3 ms+-183 us/回路(平均+-7次运行的标准偏差,每个10个回路)
f_numpy_cusum
每个循环718 us+-3.81 us(平均+-7次运行的标准偏差,每个循环1000次)您可以使用
numpy.convolve
如下所示:
k = 2
max_sum = np.max(np.convolve([2,3,5,1,6], np.ones(k,), 'same'))
使用k=2000
和len(l)=100000
此代码在我的i7机器上以0.04秒的速度运行:
from random import randint
import time
def test_max_sum(k, len_l):
num_trials = 100
total = 0
test = [randint(1, 10) for i in range(len_l)]
for i in range(num_trials):
start = time.clock()
max_sum = np.max(np.convolve(test, np.ones(k, ), 'same'))
end = time.clock()
total += end - start
total /= num_trials
print total
定义“足够快”。@OliverCharlesworth我的意思是尽可能快。实际上,您的描述是正确的,也是最快的,但实现完全错误-这不是真正的代码模式应该是有效的,不
相同
。但是输出应该是16input@AntiMatterDynamite我知道我的代码中有一个小错误,我改正了,谢谢