使用itertools.accumulate计算后缀最大值

时间:2018-02-20 22:58:23

标签: python python-3.x algorithm data-structures itertools

计算整数序列后缀最大值的推荐方法是什么?

以下是基于问题定义的蛮力方法(if时间):

-1

使用O(n**2)的一个>>> A [9, 9, 4, 3, 6] >>> [max(A[i:]) for i in range(len(A))] [9, 9, 6, 6, 6] 方法如下,它使用两个列表构造函数:

O(n)

有更多的pythonic方法吗?

2 个答案:

答案 0 :(得分:3)

切片反转使事情更简洁,嵌套更少:

list(itertools.accumulate(A[::-1], max))[::-1]

尽管如此,它仍然是你想要捆绑到一个函数中的东西:

from itertools import accumulate

def suffix_maximums(l):
    return list(accumulate(l[::-1], max))[::-1]

如果您使用的是NumPy,则需要numpy.maximum.accumulate

import numpy

def numpy_suffix_maximums(array):
    return numpy.maximum.accumulate(array[::-1])[::-1]

答案 1 :(得分:1)

我个人认为" Pythonic"我认为"简单易读[34],所以这里是我的Pythonic版本:

def suffix_max(a_list):
    last_max = a[-1]
    maxes = []
    for n in reversed(a):
        last_max = max(n, last_max)
        maxes.append(last_max)
    return list(reversed(maxes))

对于它的价值,它看起来比itertools.accumulate方法慢约50%,但我们说的是25毫秒vs 17毫秒的100,000英镑的列表,所以它可能不会很重要。

如果速度是您最关心的问题,并且您希望看到的数字范围明显小于您正在使用的列表的长度,则可能值得使用RLE

def suffix_max_rle(a_list):
    last_max = a_list[-1]
    count = 1
    max_counts = []
    for n in a_list[-2::-1]:
        if n <= last_max:
            count += 1
        else:
            max_counts.append([last_max, count])
            last_max = n
            count = 1
    if n <= last_max:
        max_counts.append([last_max, count])
    return list(reversed(max_counts))

这比以上快4倍,比itertools方法快2.5倍,对于0-10000范围内的100,000个int的列表。再次提供的是,您的数字范围明显小于列表的长度,也会占用更少的内存。