疑惑: 为什么每次滑动窗口更新时是弹出队尾而非队头
引例: 单调队列的经典例题——滑动窗口 ,求长度为
k
k
k的窗口中的最大最小值。
求最大值:维护一个单调下降的序列。
我们设第
i
i
i个窗口以第
i
i
i个元素作为右端点
对于枚举到第
i
i
i个元素,其作为当前窗口的右端点,可能是窗口的最大值。
如果枚举到第
i
−
1
i-1
i−1个元素作为窗口右端点时,若该窗口的最大值是第
i
−
k
i-k
i−k个元素,即第
i
−
1
i-1
i−1个窗口的左端点。那么继续枚举第
i
i
i个窗口时,第
i
−
k
i-k
i−k个元素已经滑出窗口,因此我们需要继续维护单调下降序列。
假设弹出队头正确:
那么如果弹出元素,必然要和第
i
i
i个元素做比较,如果弹出队头,那么说明队头小于第
i
i
i个元素。
假设现在第
i
−
k
+
1
i-k+1
i−k+1个元素小于第
i
i
i个元素,那么弹出第
i
−
k
+
1
i-k+1
i−k+1个元素,第
i
−
k
+
2
i-k+2
i−k+2个元素大于第
i
i
i个元素,那么好像是已经继续保证了单调下降序列,其实并没有。
若第
i
−
k
+
3
i-k+3
i−k+3个元素大于第
i
−
k
+
2
i-k+2
i−k+2个元素,那么实际最大的至少是第
i
−
k
+
3
i-k+3
i−k+3个元素,但是弹出队头维护单调队列得到的队头是第
i
−
k
+
2
i-k+2
i−k+2个元素。
如下:窗口长为
4
4
4,序列长为
2
2
2
序列:
1
,
4
,
10
,
8
,
9
,
7
,
6
1,4,10,8,9,7,6
1,4,10,8,9,7,6
那么第一个窗口为
1
,
4
,
10
,
8
1,4,10,8
1,4,10,8,此时单调队列为
10
,
8
10,8
10,8,符合单调队列。
第二个窗口为
4
,
10
,
8
,
9
4,10,8,9
4,10,8,9,此时单调队列为
10
,
8
,
9
10,8,9
10,8,9,符合上述弹出队头的方案,但是非单调队列,此时答案仍是对的。
第三个窗口为
10
,
8
,
9
,
7
10,8,9,7
10,8,9,7,此时单调队列为
10
,
8
,
9
,
7
10,8,9,7
10,8,9,7符合上述弹出队头的方案,但是非单调队列,此时答案仍是对的。
第四个窗口为
8
,
9
,
7
,
6
8,9,7,6
8,9,7,6此时单调队列为
8
,
9
,
7
,
6
8,9,7,6
8,9,7,6符合上述弹出队头的方案,但是非单调队列,且答案不是对的。
那么再看弹出队尾,队列暂时不包括枚举的当前元素。
那么由于之前就是单调队列,故循环判断队尾元素是否小于等于当前元素,如果是则弹出,因为第
i
i
i个元素相较于当前队列中的元素,后效性更大,即它最远可以影响到以第
i
i
i个元素作为左端点的滑动窗口。如果到某个元素停止了,说明这个元素比第
i
i
i个元素大,最后加入第
i
i
i个元素整个单调队列依然正确。