from itertools import accumulate as acc
from math import inf
from random import choices
def solution(A, K):
pre = zip(acc(A, min, initial=inf),
acc(A, max, initial=-inf))
suf = list(zip(list(acc(A[::-1], min, initial=inf))[::-1],
list(acc(A[::-1], max, initial=-inf))[::-1]))
return min(max(left[1], right[1]) - min(left[0], right[0])
for left, right in zip(pre, suf[K:]))
print(solution([3, 5, 1, 3, 9, 8], 4))
def naive(A, K):
result = inf
for i in range(len(A) + 1 - K):
copy = A.copy()
del copy[i : i+K]
result = min(result, max(copy) - min(copy))
return result
print(naive([3, 5, 1, 3, 9, 8], 4))
for _ in range(10):
A = choices(range(1000), k=100)
K = 50
expect = naive(A, K)
result = solution(A, K)
print(expect, result, result == expect)
具有前缀/后缀最小值/最大值的O(n)解:
对于您的示例
A = [3,5,1,3,9,8]
,我们有前缀minima/maxima和后缀minima/maxima:对齐
K = 4
后,您有:例如
left = (3,5)
和right = (∞,-∞)
的配对对应于移除[3,5]
后的左子阵列[3,5]
和右子阵列[]
。其中左侧和右侧的最小值为min(3,∞)=3
,最大值为max(5,-∞)=5
,振幅为5-3=2
针对naive暴力参考解决方案的十项随机测试:
整个代码(Try it online!):
相关问题 更多 >
编程相关推荐