c++ 双端队列deque 单调栈stack

本篇涉及知识点:双端队列 deque 单调栈 stack

滑动窗口的最大值

题目:P1886 最大值最小值

由于需要直到某个区间的最大值,在区间向右滑动的时候,可以拆解为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;
}

我的题解P1886 可以看一下


单调栈

找左右最近的比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;
}

猜你喜欢

转载自blog.csdn.net/zhimeng_LQ/article/details/108065838