本篇涉及知识点:双端队列 deque 单调栈 stack
滑动窗口的最大值
由于需要直到某个区间的最大值,在区间向右滑动的时候,可以拆解为R向右一位,L也向右一位。
由于我们只需要最大值,所以deque里的内容单调递减的,开头的最大,记录的是arr的【下标】
复习一下双端队列的方法
deq.front(); //返回队列首
deq.back();//返回队列尾
deq.pop_back(); //删除最后一位
deq.push_back(); //队尾加入一个
deq.empty(); //判空
deque–Code
最大值
双端队列中 由大到小
返回每个长度为size的区间内最大值
vector<int> getMaxarr(vector<int>& arr , int size){
vector<int> res; //存所有长度为size的答案
deque<int> deq;
for(int i=0;i<arr.size();i++){
//R右移
while(!deq.empty() && arr[deq.back()] < arr[i])
deq.pop_back();
deq.push_back(i);
//L左移
if(deq.front() == i-size)deq.pop_front();
if(i >= size-1){
res.push_back(arr[deq.front()]);
}
}
return res;
}
最小值
双端队列中由小到大
vector<int> getMinarr(vector<int> &arr,int size){
vector<int > res;
deque<int> deq;
for(int i=0;i<arr.size();i++){
// 小 --> 大
//R右移
while(!deq.empty() && arr[deq.back()] > arr[i]){
deq.pop_back();
}
deq.push_back(i);
//L右移
if(deq.front() == i-size)deq.pop_front();
//数据处理
if(i>=size-1){
res.push_back(arr[deq.front()]);
}
}
return res;
}
单调栈
找左右最近的比arr[i]
小的数字,单调栈
思路: 栈内由小到大存放,这样 当遍历到准备加入的数字,如果大于栈顶,压入栈,小于就弹出栈顶,因为栈顶的右侧是i,左侧答案是栈内的下一个元素,如果没有则为-1。
Code
#include <iostream>
#include <stack>
#include <vector>
#include <cstdio>
using namespace std;
const int maxn = 1000005;
int n;
int arr[maxn];
stack<int > sta;
int res[maxn][2];
int main()
{
cin>>n;
for(int i=0;i<n;i++){
cin>>arr[i];
}
//单调栈
for(int i=0;i<n;i++){
//新的 小于栈顶 弹出栈顶处理
while(!sta.empty() && arr[sta.top()]>arr[i]){
int v = sta.top();sta.pop();
int leftLessIndex = (sta.empty()) ? -1 : sta.top();
res[v][0] = leftLessIndex;
res[v][1] = i;
}
sta.push(i);
}
//没有新的要加入stack 处理栈内
while(!sta.empty()){
int v = sta.top();sta.pop();
int leftLessIndex = (sta.empty()) ? -1 : sta.top();
res[v][0] = leftLessIndex;
res[v][1] = -1;
}
//输出
for(int i=0;i<n;i++){
for(int j=0;j<2;j++){
printf("%d ",res[i][j]);
}
printf("\n");
}
return 0;
}