有一个数组为1 3 -1 -3 5 3 6 7],有一个大小为k的滑动窗口,它从数组的最左边移动到最右边。
窗口中一次性只能存在k个数字
每次滑动窗口向右移动一个位置,现在要求输出每次窗口中的最小值
例如第一次: 1 3 -1 窗口中的最小值为-1
第二次:3 -1 -3 窗口中的最小值为-3
第三次:-1 -3 5 窗口中的最小值为-3
第四次 -3 5 3 窗口中的最小值为-3 依次类推
我们的做法是维护一个单调队列,并保持队列的单调递增性,这样每次队头元素就是这个窗口中的最小值
第一次,1进队,最小元素为1
第二次,3进队,没有破坏队列的单调性,队列为[1,3],最小元素1
第三次,-1进队,1比-1大,-1出队,3比-1大,3出队 此时最小元素为-1
第四次,-3进队,-1比-3大,-1出队,此时最小元素为-3
第五次,5进队,队列为[-3,5] 维持了单调性,最小元素为-3
第六次,3进队,5比3大,不满足单调性,5出队,[-3,3]保持了单调性,
第七次,-3被滑出窗口,6进队,[3,6]保持了单调性
第八次,7入队,[3,6,7]保持了单调性
算法结束
#include <iostream>
using namespace std;
const int N = 1000010;
int q[N],a[N],hh = 0,tt = -1;
int n,k;
int main(){
cin >> n >> k;
for(int i = 0;i < n;++i) scanf("%d",&a[i]);
for(int i = 0;i < n;++i){
if(hh <= tt && i - k + 1 > q[hh]) hh++; //窗口滑动
while(hh <= tt && a[q[tt]] >= a[i]) tt--; //保持单调性
q[++tt] = i; //入队
if(i >= k - 1) printf("%d ",a[q[hh]]); //队列中满足k个元素时才输出
}
return 0;
}