算法-单调栈

单调栈就是栈中元素单调递增或递减

主要用于找到每一个元素左边或右边,第一个比它大或小的数。

例如维护一个单调递增的栈,取一组元素为5,3 ,4 ,7,2,9;

step:5入栈;

   3入栈发现栈顶元素5大于3弹出5,发现栈为空,3入栈。

   4入栈,发现栈顶元素比4小,直接入栈

   7同理直接入栈

   2入栈,2是最小的,弹出所有元素入栈

   9直接入栈

所以栈中最终的元素是2,9。

从中可以发现一个规律,每个元素入栈的过程,都是在找左边第一个比它小的元素过程,如果直接入栈,那么栈顶元素就是当前元素的左边的第一个小于它的元素,相反入栈元素就是栈顶元素的第一个大于它的数。

复杂度分析:整个过程遍历了一遍数组,由于每个元素只会入栈和出栈一次,整个过程的时间复杂度为O(n)。

例题1:Acwing830. 单调栈

给定一个长度为 N 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出 1

示例输入:

5

3 4 2 7 5

示例输出:-1 3 -1 2 2

c++代码

复制代码
#include<iostream>
#include<stack>
using namespace std;
const int N=1e5+5;
int n;
int stk[N],top=0;
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int t;  
        cin>>t;        
        while(top && stk[top]>=t)top--;      //如果栈非空并且栈顶元素比插入元素大,弹出元素 
        if(top)                              //检查栈顶是否有元素,有则输出栈顶元素,没有就输出-1 
            cout<<stk[top]<<endl;
        else
            cout<<-1<<endl;
        stk[++top]=t;                     //插入元素 
    }
    return 0;
} 
复制代码

Java代码

复制代码
import java.util.Scanner;
public class Main{
    static final int N=100010;
    static int[] stk= new int[N];
    static int top=0;
    public static void main(String[] args)
    {
        Scanner in=new Scanner(System.in);
        int n=in.nextInt();
        for(int i=0;i<n;i++)
        {
            int t=in.nextInt();
            while(top!=0 &&stk[top]>=t) top--;
            if(top!=0)System.out.print(stk[top]+" ");
            else System.out.print(-1+" ");
            stk[++top]=t;
        }
    }
}
复制代码

例题二:Acwing131. 直方图中最大的矩形

直方图是由在公共基线处对齐的一系列矩形组成的多边形。

矩形具有相等的宽度,但可以具有不同的高度。

例如,图例左侧显示了由高度为 2,1,4,5,1,3,32,1,4,5,1,3,3 的矩形组成的直方图,矩形的宽度都为 11:

2559_1.jpg

通常,直方图用于表示离散分布,例如,文本中字符的频率。

现在,请你计算在公共基线处对齐的直方图中最大矩形的面积。

图例右图显示了所描绘直方图的最大对齐矩形。

示例输入:

7 2 1 4 5 1 3 3

4 1000 1000 1000 1000

0

示例输出:

8

4000

c++代码

复制代码
#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int n;
int h[N],l[N],r[N],q[N];
int main()
{
    while(scanf("%d",&n),n)
    {
        for(int i=1;i<=n;i++)
            cin>>h[i];    
        h[0]=-1,h[n+1]=-1;
        int top=0;
        q[0]=0;
        for(int i=1;i<=n;i++)
        {
            while(h[q[top]]>=h[i])top--;
            l[i]=q[top];
            q[++top]=i;
        }
        top=0;
        q[0]=n+1;
        for(int i=n;i;i--)
        {
            while(h[q[top]]>=h[i])top--;
            r[i]=q[top];
            q[++top]=i;
        }
        LL ans=0;
        for(int i=1;i<=n;i++)
        {
            ans=max(ans,(LL)h[i]*(r[i]-l[i]-1));
        }
        cout<<ans<<endl;
    }
    return 0;
} 
复制代码

 









 

posted @   Xhxxx  阅读(3165)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示