计算整数序列后缀最大值的推荐方法是什么?
以下是基于问题定义的蛮力方法(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方法吗?
答案 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的列表。再次提供的是,您的数字范围明显小于列表的长度,也会占用更少的内存。