目录
题目链接
描述
给定一个长度为n(n<=10^6)的数组。有一个大小为k的滑动窗口从数组的最左端移动到最右端。你可以看到窗口中的k个数字。窗口每次向右滑动一个数字的距离。
下面是一个例子:
数组是 [1 3 -1 -3 5 3 6 7], k = 3。
窗口位置 | 最小值 | 最大值 |
---|---|---|
[1 3 -1] -3 5 3 6 7 | -1 | 3 |
1 [3 -1 -3] 5 3 6 7 | -3 | 3 |
1 3 [-1 -3 5] 3 6 7 | -3 | 5 |
1 3 -1 [-3 5 3] 6 7 | -3 | 5 |
1 3 -1 -3 [5 3 6] 7 | 3 | 6 |
1 3 -1 -3 5 [3 6 7] | 3 | 7 |
你的任务是得到滑动窗口在每个位置时的最大值和最小值。
输入
输出
样例输入
8 3 1 3 -1 -3 5 3 6 7
样例输出
-1 -3 -3 -3 3 3 3 3 5 5 6 7
解题思路
视频链接:
9.74 单调队列 滑动窗口最大值——信息学竞赛培训课程_哔哩哔哩_bilibili
老师讲的通俗易懂,看不懂代码的同学可以去看看。
C++代码:
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int a[N],q[N];
int n,k;
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
//最小值队列 建立单调递增队列
int h=0,t=-1;
for(int i=1;i<=n;i++){
if(t>=h&&q[h]<i-k+1) h++;
while(t>=h&&a[i]<=a[q[t]]) t--;
q[++t]=i;
if(i>=k)
printf("%d ",a[q[h]]);
}
printf("\n");
//最大值队列 建立单调递减队列
h=0,t=-1;
for(int i=1;i<=n;i++){
//队列中有元素且队头元素不在窗口[i-m+1,i]内,队头出队
if(h<=t&&q[h]<i-k+1)
h++;
//队列中有元素且当前值>=队尾值,队尾出队
while(h<=t&&a[i]>=a[q[t]])
t--;
//下标入队,便于队头出队
q[++t]=i;
//使用队头最大值
if(i>=k)
printf("%d ",a[q[h]]);
}
return 0;
}
C++双向队列:
#include<iostream>
#include<deque>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int a[N];
int n,k;
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
deque<int>q;
//升序找最小
for(int i=1;i<=n;i++){
if(!q.empty()&&q.front()<i-k+1)
q.pop_front();
while(!q.empty()&&a[i]<=a[q.back()])
q.pop_back();
q.push_back(i);
if(i>=k)
printf("%d ",a[q.front()]);
}
printf("\n");
q.clear();
//降序找最大
for(int i=1;i<=n;i++){
if(!q.empty()&&q.front()<i-k+1)
q.pop_front();
while(!q.empty()&&a[i]>=a[q.back()])
q.pop_back();
q.push_back(i);
if(i>=k)
printf("%d ",a[q.front()]);
}
return 0;
}
原文地址:https://www.jb51.cc/wenti/3287796.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。