• 数组模拟队列&栈


    数组模拟队列&栈

    #include<iostream>
    
    using namespace std;
    
    const int N=100010;
    
    int stk[N],tt;//栈一般定义为stk[N],tt为栈点下标,栈习惯上从0开始
    //插入 
    skt[++tt]=x;//表示在栈顶加入一个新的元素 
    //弹出
    tt--;
    //判断栈是否为空
    if(tt>0)//说明不空
    else //empty 
    //栈顶元素
    stk[tt]; 
    

    队列

    //模拟队列
    int q[N],hh,tt=-1;//队列习惯上从-1开始
    //插入
    q[++tt]=x;
    //弹出
    hh++;//将队头的指针向后移动一位则为弹出
    //判断是否为空
    if(hh<=tt) not empty
    else empty
    //取出队头元素
    q[hh];
    //还可以取出队尾
    q[tt]; 
    

    单调栈

    题目:

    输入一串数字,找到每一个数字所对应的在他左边离他最近且比他小的数,如果有这个数,则输出,若无,则输出-1

    #include<iostream>
    
    using namespace std;
    
    const int N=100010;
    
    int n;
    int stk[N],tt;
    
    int main()
    {
    	cin>>n;
    	for(int i=0;i<n;i++)
    	{
    		int x;
    		cin>>x;
    		while(tt&&stk[tt]>=x) tt--;//当栈非空并且栈顶元素大于此时读入的这个x,那么这个栈顶元素就再也不会被用到了,因为要让序列为单调递增 
    		if(tt) cout<<stk[tt]<<' ';//若栈非空,则说明该栈顶元素为离他最近的一个小于它的元素
    		else	cout<<-1<<' ';//否则说明找不到这样的数,则返回-1
    		
    		stk[++tt]=x;//最后要记得把该数再插回到队列当中
    	}
    	return 0;
    }
    

    单调队列

    题目:

    给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

    返回滑动窗口中的最小值和最大值。

    示例 1:
    
    输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
    输出:	[-1,-3,-3,-3,3,3]
    	  [3,3,5,5,6,7]
    解释:
    滑动窗口的位置                最大值
    
    ---------------               -----
    
    [1  3  -1] -3  5  3  6  7       3
     1 [3  -1  -3] 5  3  6  7       3
     1  3 [-1  -3  5] 3  6  7       5
     1  3  -1 [-3  5  3] 6  7       5
     1  3  -1  -3 [5  3  6] 7       6
     1  3  -1  -3  5 [3  6  7]      7
    
    

    思路:

    用一个队列来存,当窗口在滑动时,将即将要滑到的元素插入到队尾,将即将要划走的元素从队头弹出来。

    在找到最值时,若用遍历枚举的话,会造成时间复杂度高,则此处和单调栈相同思路,先用暴力做法,再看在栈和队列中有哪些元素是没有用到的,将这些元素删掉后,再去看剩下的元素是否具有单调性,即可优化:

    若取极值则取端点,若取某个点则用二分法

    代码:

    #include<iostream>
    
    using namespace std;
    
    const int N=1000010;
    
    int n,k;
    int a[N],q[N];//a存原来的值,q存的是单调队列
     
    int main()
    {
    	scanf("%d%d",&n,&k);
    	for(int i=0;i<n;i++) scanf("%d",&a[i]);
    	
    	//最小值队列 
    	int hh=0,tt=-1;//定义一下队头和队尾 
    	for(int i=0;i<n;i++)
    	{
    		//判断队头是否已经滑出窗口 
    		if(hh<=tt &&i-k+1>q[hh])//前者判断是否空 ,后者判断是否已经滑出窗口 
    			hh++;
    		while(hh<=tt && a[q[tt]]>=a[i])
    			tt--;//若队尾的数大于或等于即将进来的数,则将队尾的数出队 
    		q[++tt]=i;//将当前的数插到队列中 
    		if(i>=k-1) printf("%d ",a[q[hh]]);// 
    	}
    		puts("");
    		
    		
    	//最大值与最小值完全一致	
    	hh=0,tt=-1;//定义一下队头和队尾 
    	for(int i=0;i<n;i++)
    	{
    		//判断队头是否已经滑出窗口 
    		if(hh<=tt &&i-k+1>q[hh])//前者判断是否空 ,后者判断是否已经滑出窗口 
    			hh++;
    		while(hh<=tt && a[q[tt]]<=a[i])
    			tt--;//若队尾的数大于或等于即将进来的数,则将队尾的数出队 
    		q[++tt]=i;//将当前的数插到队列中 
    		if(i>=k-1) printf("%d ",a[q[hh]]);// 
    	}
    		puts("");
    		return 0;
    } 
    
  • 相关阅读:
    IIS重定向通配符说明
    Powershell小技巧
    WPF学习笔记三 依赖属性
    Visual Studio .NET加密技术剖析系列课程(视频课程讲师:王为)
    OBA开发系列课程(视频课程讲师:钟伟)
    深度剖析Workflow Foundation系列课程(视频课程讲师:徐晓卓)
    从架构设计到系统实施——基于.NET 3.0的全新企业应用系列课程(视频课程讲师:徐晓卓)
    Silverlight风云演义系列课程(视频课程讲师:王洪超)
    微软高性能运算系列课程(视频课程讲师:任旻、张海忠)
    Microsoft Office Sharepoint Server 2007开发系列课程(视频课程讲师:鞠海洋)
  • 原文地址:https://www.cnblogs.com/fzujly/p/14648064.html
Copyright © 2020-2023  润新知