给定N个正整数数组,范围从索引0到N-1,我如何找到长度为K且具有最小范围的连续子数组。换句话说,将max(subarray)-min(subarray)最小化。如果有多个答案,则可以。
例如,找到长度为2的子数组,其范围从[4,1,2,6]最小。
答案将是[1,2],因为2-1 = 1给出了所有可能的连续子数组的最小范围。
其他子数组是[4,1](范围3),[2,6](范围4)
我正在使用python,到目前为止,我已经尝试使用min()max()函数进行线性搜索,但这样做似乎效率不高。我曾经考虑过使用Minheap,但是我不确定您将如何实现它,甚至不确定它是否会起作用。任何帮助将不胜感激。
编辑:已添加代码
# N = length of array_of_heights, K = subarray length
N, K = map(int, input().split(' '))
array_of_heights = [int(i) for i in input().split(' ')]
min_min = 100000000000000000000
# iterates through all subarrays in the array_of_heights of length K
for i in range(N + 1 - K):
subarray = land[i : i + K]
min_min = min(max(subarray)-min(subarray), min_min)
print(min_min)
答案 0 :(得分:1)
您可以使用numpy来缩短执行时间。
示例:
def f1(l,k):
subs = np.array([l[i:i+k] for i in range(len(l)-k+1)])
return np.min(subs.max(axis=1) - subs.min(axis=1))
小测试(f2
是您的功能)。
>>> arr = np.random.randint(100,size=10000)
>>> timeit.timeit("f1(arr,4)",setup="from __main__ import f1,f2,np,arr",number=1)
0.01172515214420855
>>> timeit.timeit("f2(arr,4)",setup="from __main__ import f1,f2,np,arr",number=1)
14.226237731054425
答案 1 :(得分:1)
linear-time algorithm O(N)
用于在指定大小的移动窗口中获取最小值或最大值(而您的实现复杂度为O(N*K)
)
使用deque
模块中的collections
,您可以实现两个并行双端队列,保持当前窗口位置的最小值和最大值,并在仅遍历列表后检索最佳差值。
import collections
def mindiff(a, k):
dqmin = collections.deque()
dqmax = collections.deque()
best = 100000000
for i in range(len(a)):
if len(dqmin) > 0 and dqmin[0] <= i - k:
dqmin.popleft()
while len(dqmin) > 0 and a[dqmin[-1]] > a[i]:
dqmin.pop()
dqmin.append(i)
if len(dqmax) > 0 and dqmax[0] <= i - k:
dqmax.popleft()
while len(dqmax) > 0 and a[dqmax[-1]] < a[i]:
dqmax.pop()
dqmax.append(i)
if i >= k - 1:
best = min(best, a[dqmax[0]]-a[dqmin[0]])
return best
print(mindiff([4, 1, 2, 6], 2))