Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/292.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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 如何有效地找到最小长度的峰值?_Python_Algorithm - Fatal编程技术网

Python 如何有效地找到最小长度的峰值?

Python 如何有效地找到最小长度的峰值?,python,algorithm,Python,Algorithm,我有一个整数的列表/数组,如果一个子数组先升后降,就称它为峰值。例如: [5,5,4,5,4] 包含 [4,5,4] 这是一个高峰 也考虑 [6,5,4,4,4,4,4,5,6,7,7,7,7,7,6] 其中包含 [6,7,7,7,7,7,6] 这是一个高峰 问题 给定一个输入列表,我想找到其中包含的最小长度的所有峰值并报告它们。在上面的示例中,[5,6,7,7,7,7,6]也是一个峰值,但我们删除了第一个元素,它仍然是一个峰值,因此我们不报告它 因此,对于输入列表: L = [5,5,

我有一个整数的列表/数组,如果一个子数组先升后降,就称它为峰值。例如:

[5,5,4,5,4]
包含

[4,5,4]
这是一个高峰

也考虑

[6,5,4,4,4,4,4,5,6,7,7,7,7,7,6]
其中包含

[6,7,7,7,7,7,6]
这是一个高峰

问题 给定一个输入列表,我想找到其中包含的最小长度的所有峰值并报告它们。在上面的示例中,
[5,6,7,7,7,7,6]
也是一个峰值,但我们删除了第一个元素,它仍然是一个峰值,因此我们不报告它

因此,对于输入列表:

L = [5,5,5,5,4,5,4,5,6,7,8,8,8,8,8,9,9,8]
我们会回来的

[4,5,4] and [8,9,9,8] only.
我在设计一个好的算法时遇到了问题。非常感谢您的帮助。

使用
itertools
下面是一个用于检测峰值的简短解决方案。识别峰值的组随后被解包以产生实际序列

from itertools import groupby, islice

l = [1, 2, 1, 2, 2, 0, 0]

fst, mid, nxt = groupby(l), islice(groupby(l), 1, None), islice(groupby(l), 2, None)
peaks = [[f[0], *m[1], n[0]] for f, m, n in zip(fst, mid, nxt) if f[0] < m[0] > n[0]]

print(peaks)
使用循环(更快) 上面的解决方案很优雅,但由于创建了三个
groupby
实例,因此该列表被遍历三次

下面是一个使用单个遍历的解决方案

def peaks(lst):
    first = 0
    last = 1
    while last < len(lst) - 1:
        if lst[first] < lst[last] == lst[last+1]:
            last += 1
        elif lst[first] < lst[last] > lst[last+1]:
            yield lst[first:last+2]
            first = last + 1
            last += 2
        else:
            first = last
            last += 1

l = [1, 2, 1, 2, 2, 0, 0]
print(list(peaks(l)))
关于基准的说明
在使用
timeit
进行基准测试时,我注意到使用循环的解决方案的性能提高了约20%。对于短列表,
groupby
的开销可能会使这个数字达到40%。基准测试是在Python 3.6上完成的。

所以[4,5,5,4]也被认为是一个峰值?@OlivierMelançon Yes类似于[4,5,5,2]的东西是什么?或者元素保证只改变1。@IFunball这也是一个峰值。但是当它们只改变1时,你有更简单的方法吗?@IFunball我建议的解决方案适合你的需要吗?函数似乎缺少一个返回语句?@Anush它是一个生成器,它是峰值。当列表可能相当长时,这是一个很好的实践。不管怎样,一个生成器总是可以被制作成一个列表和一个演员表。谢谢。你的答案很好。
def peaks(lst):
    first = 0
    last = 1
    while last < len(lst) - 1:
        if lst[first] < lst[last] == lst[last+1]:
            last += 1
        elif lst[first] < lst[last] > lst[last+1]:
            yield lst[first:last+2]
            first = last + 1
            last += 2
        else:
            first = last
            last += 1

l = [1, 2, 1, 2, 2, 0, 0]
print(list(peaks(l)))
[[1, 2, 1], [1, 2, 2, 0]]