7月24号题解

滑动窗口最大值

*****************************************************************

如果使用纯暴力复杂度为(k*n) 但使用单调队列的方式可以让复杂度变为(n) ,单调队列的方式,维护一个单调递减的队列,我们让队首永远维护这个滑动窗口的最大值,将边界设为(1-k,n-k),当i比0大的时候就可以队列的首项就是这个窗口的最大值

{  
    // 使用双端队列来维护滑动窗口中的最大值索引  
    deque<int> p;    
    vector<int> ans(nums.size() - k + 1);  
      
    // 初始化循环变量,i 用于结果数组的索引,j 用于遍历 nums 数组  
    // 注意这里 i 的初始值是 1-k,因为当 j=0 时,窗口还未完全形成(除非 k=1)  
    // 所以此时不记录结果到 ans 中  
    for(int j = 0, i = 1 - k; j < nums.size(); i++, j++)  
    {  
        // 如果当前窗口的起始位置已经超过了数组边界,并且队列的前端是该起始位置的元素  
        // 那么移除它,因为新的窗口已经不包含它了  
        if(i > 0 && p.front() == nums[i - 1])  
        {  
            p.pop_front();  
        }  
          
        // 移除队列后端所有小于当前元素的索引,因为它们不可能是当前窗口的最大值  
        while(!p.empty() && p.back() < nums[j])  
        {  
            p.pop_back();  
        }  
          
        // 将当前元素的索引加入队列  
        p.push_back(j);  
          
        // 如果当前窗口的起始位置已经在数组范围内,记录当前窗口的最大值到结果数组中  
        // 队列的前端始终是窗口中的最大值索引  
        if(i >= 0)  
        {  
            ans[i] = nums[p.front()];  
        }  
    }  
      
    // 返回包含每个窗口最大值的数组  
    return ans;  
}js

单调栈找左右比它小的值

单调栈可以找到某个数后面比它(大或小的数),但现在要解决的是如何维护左右的比它小的值呢。当某个数比它小是我们就可以把栈顶弹出,这里想一下是什么样的数被它压着,前面说了小的能使大的弹出,说明被它压住的是比它小的。当判断完我们会发现栈里还有剩的,说明后面已经没有让它们可以弹出栈的条件了。但左区间还没有判断完。所以要把栈清空

using namespace std;
const int N=1e5+10;
int a[N],l[N],r[N];
/*
例子 8
2 5 6 7 3 4 1 8
左 -1 1 2 3 1 5 -1 7
右 7 5 5 5 7 7 -1 -1
*/
int main()
{
	stack<int> p;
	int n;
	cin>>n;	
	for(int i=1;i<=n;i++) {
		cin>>a[i];
		l[i]=r[i]=-1;//初始化 
	}
	for(int i=1;i<=n;i++)
	{
		while(!p.empty()&&a[p.top()]>a[i]) 
		{//栈非空且入栈元素小于栈顶,需要清算 
			int cur=p.top();//弹出当前栈顶 
			p.pop();
			r[cur]=i;//右边第一个小的元素是 i 
			if(!p.empty()) l[cur]=p.top();// 左边第一个小的数是当前栈顶 
		}
		p.push(i);//栈内单调性调整完毕,压入 i 
	}
	while(!p.empty())// 栈内留下的未弹出的元素 
	{
		int cur=p.top();
		p.pop();
		if(!p.empty()) l[cur]=p.top();
		//最后清算阶段的元素只有左边小,没有右边 
	}
	for(int i=1;i<=n;i++)
	{
		cout<<l[i]<<' ';
	}
	cout<<endl;
	for(int i=1;i<=n;i++)
	{
		cout<<r[i]<<' ';
	}
	return 0;
}
#题解#
全部评论

相关推荐

2025-12-06 01:10
已编辑
哈尔滨工程大学 Java
一面问的真细,二面不知为啥变双机位。9.29快手主站平时怎么学习&nbsp;AI&nbsp;的,国内外知名大模型,实习公司都用的什么大模型,怎么评估效果的java池化思想,线程池构造方法的核心参数,线程池中阻塞队列注意事项,submit方法参数和执行逻辑,shutdown和shutdownnow,核心线程允许过期吗threadlocal底层,为什么key是弱引用,key回收了再get或者set这个value会怎样aqs,如何保证公平性java代理java堆划分,新生代还有别的晋升老年代的情况吗,什么时候触发gc,gc失败抛什么异常,如何排查oom,导出dump命令redis数据结构,哪个底层是跳表,和其他数据结构对比布隆过滤器会出现大key问题吗,你咋实现的布隆过滤器你怎么实现redis分布式锁,可重入,续期聚簇索引非聚簇索引select语句会加锁吗,怎么实现的不加锁undolog&nbsp;redolog&nbsp;binlog怎么能让select加锁,update这个范围加的什么锁,update一条呢手撕简单01背包,接雨水10.10快手主站意图识别用的哪个大模型,走到意图和rag的比例,faq是点击的吗自然语言怎么识别的gap一年干啥了,转正怎么样没跟组里提意向吗,研究生研究方向是传统算法吗,会大模型微调吗注册场景为什么用布隆过滤器,原理分布式锁底层的key怎么拼的,value里是什么redis持久化zset底层mysql索引结构,一个表三个字段有主键唯一索引和没索引的字段会有几个b+树,聚簇索引非聚簇索引存的啥无手撕
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务