Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/296.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列表算法中k个连续数最大和的执行时间_Python_Algorithm - Fatal编程技术网

如何减少python列表算法中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]

我的问题是找到给定列表中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]
        if temp > M:
            M = temp
    return M
但不幸的是,它只适用于k=2? 因此,我有两个问题:

  • 为什么我的代码不能与更高的k一起工作?(错误是什么?我如何修复它?)
  • 有没有更好的方法(时间方面)来解决主要问题?如果len(l)=100000和k=2000,该算法是否足够快?如何仅通过查看代码来确定其执行时间
    为此,我们应该使用动态规划,并在
    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项的总和,而不是0
  • 开始时的代码范围> k>代码>数字应该是<代码> N-K+ 1 ,在窗口大小为k</LI>的序列中的最大位置。
  • 您的
    temp
    相当于
    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
    
  • 时间复杂度为O(N),内存复杂度为O(1)。实际上,对于长序列,@dobbind使用卷积的方法可能是最快的

    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我知道我的代码中有一个小错误,我改正了,谢谢