题目
对于一个长度为 n 的数组,有长度为 m(m ≤ n)的滑动窗口,要求滑动到每一个点时,窗口区域内的最(大/小)值。
解题
如果使用暴力,在每一段之内求max,那么时间复杂度为O(m*n)
而使用单调队列算法,可以在O(n)内解决该问题
数据结构
算法维护了一个下标对应的元素单调增减的队列(是的,q里存的是数组下标)
求最小值时要求单调递增;求最大值时则要求单调递减(是不是有点反直觉)
核心思想(我理解的)是判断元素是否有成为最值的潜力
以上题目的解题代码和注释如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| if __name__ == '__main__': n, k = map(int, input().split()) a = list(map(int, input().split()))
q = [0 for i in range(n)] hh, tt = 0, -1 for i in range(n): if hh <= tt and q[hh] < i - k + 1: hh += 1 while hh <= tt and a[q[tt]] >= a[i]: tt -= 1 tt += 1 q[tt] = i
if i >= k - 1: print(a[q[hh]])
hh, tt = 0, -1 for i in range(n):
if hh <= tt and q[hh] < i - k + 1: hh += 1
while hh <= tt and a[q[tt]] <= a[i]: tt -= 1 tt += 1 q[tt] = i
if i >= k - 1: print(a[q[hh]])
|