题意如下文所示:
题目描述
给你一个长度为 N 的数组,一个长为 K 的滑动的窗体从最左移至最右端, 你只能见到窗口的K个数,每次窗体向右移动一位,你的任务是找出窗口在各位置时的 max value,min value.
输入格式
第 1 行 n,k, 第 2 行为长度为 n 的数组
输出格式
2 行, 第 1 行每个位置的 min value, 第 2 行每个位置的 max value
样例数据
input
8 3
1 3 -1 -3 5 3 6 7
output
-1 -3 -3 -3 3 3
3 3 5 5 6 7
数据规模与约定
20%: n<=500;
50%: n<=100000;
100%: n<=1000000;
时间限制:1s1s
空间限制:256MB256MB
主要思路: 控制窗户移动,进队时与现在窗户的前几个数进行比较,粗暴点来说就是把比自己小或者大(找小的挤大的,找大的挤小的)的给挤出队列,定义头指针head指队首,尾指针tail指队尾,一次次比队尾,指针指队尾(因为要挤出所以不停变换)最后这个窗户的队首一定是次窗户中最小或最大的,输出即可,但要注意空格。
#include<bits/stdc++.h>
using namespace std;
int a[1000010],zhi[1000010],n,k,head=1,tail=0;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
if(i-zhi[head]>=k)head++; //移动窗户
while(a[i]<a[zhi[tail]]&&head<=tail)tail--; //与队尾比较,如果比队尾小且还有数,则队尾指向前一个数,再进行比较
zhi[++tail]=i; // 队尾指向此数
if(i>=k)
{
if(i==n) //如果i是最后一个数输出现在窗口最小数并换行
cout<<a[zhi[head]]<<endl;
else
cout<<a[zhi[head]]<<' '; //主要注意空格
}
}
memset(zhi,0,sizeof(zhi));//指针清空,准备找窗口最大数
head=1;tail=0;//同样回到原始
for(int i=1;i<=n;i++)
{
if(i-zhi[head]>=k)head++;
while(a[i]>a[zhi[tail]]&&head<=tail)tail--;//与队尾比较,如果比队尾大且还有数,则队尾指向前一个数,再进行比较
zhi[++tail]=i;
if(i>=k)
{
if(i==n)
cout<<a[zhi[head]]<<endl;
else
cout<<a[zhi[head]]<<' ';
//基本与找最小值一样
}
}
return 0;
}