滑动窗口(单调队列)
拿求窗口里的最小值来说,如果这个数在i位置的前面,还比i位置上的数大,那么无论窗口向后移动多少位,这个数永远不可能是最小值,所以将其从队列中拿出.
#include <bits/stdc++.h>
using namespace std;
#define MAX 1000010
int nArr[MAX];//存储数组的值
int nQueue[MAX];//队列 里面存储数组的下标
int nSize;
int nWindow;
int main(int argc, char** argv)
{
scanf("%d",&nSize);
scanf("%d",&nWindow);
//将数组中的元素读取
for(int i = 0; i < nSize; i++)
{
scanf("%d",&nArr[i]);
}
int nHead = 0;
int nTail = -1;
for(int i = 0; i < nSize; i++)
{
if(nHead <= nTail && (i - nWindow + 1) > nQueue[nHead])
{
//nHead <= nTail保证队列中有元素
//(i-nWindow+1)与nQueue[nHead]比较 保证当前的下标还在窗口里面
nHead++;
}
while(nHead <= nTail && nArr[nQueue[nTail]] >= nArr[i])
{
//在i位置以前的数 还比nArr[i]大的 ,他们的下标都要从里面去除
nTail--;
}
//当前数组元素入队列
nQueue[++nTail] = i;
if(i >= nWindow - 1)
{
printf("%d ",nArr[nQueue[nHead]]);
}
}
printf("\n");
nHead = 0;
nTail = -1;
for(int i = 0; i < nSize; i++)
{
if(nHead <= nTail && (i - nWindow + 1) > nQueue[nHead])
{
//nHead <= nTail保证队列中有元素
//(i-nWindow+1)与nQueue[nHead]比较 保证当前的下标还在窗口里面
nHead++;
}
while(nHead <= nTail && nArr[nQueue[nTail]] <= nArr[i])
{
//在i位置以前的数 还比nArr[i]小的 ,他们的下标都要从里面去除
nTail--;
}
nQueue[++nTail] = i;
if(i >= nWindow - 1)
{
printf("%d ",nArr[nQueue[nHead]]);
}
}
return 0;
}