单调递减队列
来源:互联网 发布:进销存系统数据库设计 编辑:程序博客网 时间:2024/06/02 07:31
题意:
给定一个长度为n的序列,有一个长度为k的滑动窗口,窗口从左向右依次移动,求每次移动时窗口中的最大值。
算法实现:
1.有一种很常见的算法,时间复杂度为O(n*k)的算法,线性遍历每个数再求每个滑动窗口中的最大值,、但当k很大的时候非常耗时。
2.还有一中就是单调递减队列,可以把时间复杂度优化到接近O(n),既然是单调队列,那我们就要定义一个队列,而且还要是双端的。下面我们模拟一下。
假定这个序列的k为3,那我们从第一个元素开始访问,这个时候我们有一个空的双端队列que。我们先把第一个元素及下标入队,队列为{(1,1)},然后开始访问第二个元素,把第二个元素的值与第一个元素的值比较,如果小于则往队列后面加,否则将他前面的一个元素删除,直至遇到比它大的为止,然后将它加入队列。这个队列中就变成了{(3,2)}。继续操作,队列变成{(3,2),(-1,3)}、{(3,2),(-1,3),(-3,4)}、{(3,2),(-1,3),(-3,4),(-4,5)},而这时,我们可以看到队列中的元素个数大于了k,而这时我们应该判断队首元素下标是否小于i-k+1,如果小于则删除队首元素。依照此操作重复进行,直到整个序列遍历完成。在我们入队的时候其实可以只入队下标,用下标来查找元素。
代码如下:
#include<iostream>#include<cstdio>#include<deque>using namespace std;int n,k;int cnt = 0;int a[100002];int id[100002];int ans[100002];deque<int>que;void getmax(){ for(int i = 1;i <= n; i++){ while(!que.empty() && a[que.back()] <= a[i])que.pop_back();//比较并删除元素 que.push_back(i);//添加元素 while(!que.empty() && que.front() < i-k+1)que.pop_front();//检查是否超出k ans[cnt++] = que.front();//记录答案 }}int main(){ scanf("%d%d",&n,&k); for(int i = 1;i <= n; i++)scanf("%d",&a[i]); getmax(); for(int i = k-1;i < cnt; i++)printf("%d ",a[ans[i]]);//输出要从k-1开始输出。}
0 0
- 单调递减队列
- uva1427 - Parade 单调队列 维护递减数列
- openjudge滑动窗口(单调递增递减队列)
- 算法:C++实现先递增后递减队列的最值和单调递增队列的绝对值最小的值
- 最长单调递减子序列
- HDU1069(最长单调递减数列)
- 最长单调递减子序列
- 单调栈 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 单调队列
- 前和讯新浪微博高级工程师姚飞:合作,共赢。
- 地图开发专家Blog
- 四组对象和级联
- 利用soot插装Android App
- ubifs文件系统制作
- 单调递减队列
- SET XACT_ABORT ON
- 新计划
- 怎么用网盘查找资源
- Chapter 9: Mixture Models and EM
- TIJ_字符串
- LCD 调试问题总结
- 不同根视图下控制部分屏幕旋转(tabbarController/navigationController)
- 337. House Robber III