LeetCode 热题100——单调栈

  个人主页:日刷百题

系列专栏〖C语言小游戏〗〖Linux〗〖数据结构〗 〖C语言〗

🌎欢迎各位点赞👍+收藏⭐️+留言📝 

 写在前面:

递增单调栈:栈中元素从栈底到栈顶依次增大
递减单调栈:栈中元素从栈底到栈顶依次减小

在学习完朴素的数据结构栈之后,单调栈作为栈的一种升级版应用,在某些情境下具有得天独厚的优越性:可将O(n²)的遍历复杂度降低至O(n)

以下就是几种经典的单调栈运用问题。

一、字符串解码 

 

 思路:这题利用了栈,但不是单调栈,我们看到括号问题容易联想到有效括号问题也是利用栈

(1)遍历字符数组,当没有遇到‘]’时,将字符全部入栈

(2)若遇到‘]’,将字母一一出栈,入到临时栈,直到遇到‘[’停止

(3)此时将'['出栈,此时栈顶必然是数字字符,将数字字符全部转化为mulsize数字,出栈

(4)用2层嵌套循环,外层为mulsize,内层为临时栈的元素个数,将临时栈元素按mulszie次循环放进栈中,最后将临时栈初始化

(5)最后,字符遍历结束,栈中元素即为所求,此时将栈的末尾加上’\0’.

注:这里值得注意的地方有俩点

<1>在栈末尾插入‘\0’,得有扩容判断

<2>在将数字字符转化为mulsize时,字符数字是一个个出栈,为逆序,例如:100出栈为001,所以转化为数字的时候,要注意

typedef char DateType;
typedef struct Stack
{DateType* a;int top;int capacity;
}Stack;
//初始化和销毁栈
void InitStack(Stack* ps)
{assert(ps);ps->a = NULL;ps->top = ps->capacity = 0;
}
void DestoryStack(Stack* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = 0;ps->capacity = 0;
}//出栈和入栈
void StackPush(Stack* ps, DateType x)
{assert(ps);if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;DateType* tmp = (DateType*)realloc(ps->a, sizeof(DateType) * newcapacity);if (tmp == NULL){perror("realloc fail:");return;}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] = x;ps->top++;
}
void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}//栈的有效个数和栈顶元素
int StackSize(Stack* ps)
{assert(ps);return ps->top;
}
DateType StackTop(Stack* ps)
{assert(ps);assert(ps->top > 0);return   ps->a[ps->top - 1];
}
//判空
bool IsEmptyStack(Stack* ps)
{assert(ps);return ps->top == 0;
}
char* decodeString(char* s) {Stack ps;Stack tmp;InitStack(&ps);InitStack(&tmp);int len = strlen(s);while ((*s) != '\0'){if ((*s) != ']'){StackPush(&ps, (*s));}else{while (StackTop(&ps) != '['){char b = StackTop(&ps);StackPop(&ps);StackPush(&tmp, b);}StackPop(&ps);int tmpsize = tmp.top;int mulsize=0;int i=0;while (ps.top > 0 && ps.a[ps.top - 1] >= '0' && ps.a[ps.top - 1] <= '9'){mulsize =mulsize  + pow(10,i)*(ps.a[ps.top - 1] - '0');StackPop(&ps);i++;}for (int i = 0; i < mulsize; i++){for (int j = 0; j < tmpsize; j++){char w = StackTop(&tmp);StackPush(&ps, w);StackPop(&tmp);}tmp.top = tmpsize;}}if (tmp.a != NULL){free(tmp.a);tmp.a = NULL;InitStack(&tmp);}s++;}DestoryStack(&tmp);if (ps.top == ps.capacity){int newcapacity = ps.capacity == 0 ? 4 : 2 * ps.capacity;DateType* tmp = (DateType*)realloc(ps.a, sizeof(DateType) * newcapacity);if (tmp == NULL){perror("realloc fail:");return 1;}ps.a = tmp;ps.capacity = newcapacity;}ps.a[ps.top] = '\0';return ps.a;
}

 二、接雨水

思路:这题思路比较巧妙,运用了单调递减栈

(1)创造栈用来存放数组元素下标

(2)遍历数组,若栈为空或者栈顶元素所对应的数组值大于等于数组元素,则直接入栈

(3)若栈顶元素所对应数组元素值小于数组元素,则做出判断,将栈顶元素保存,且出栈,再用此时的栈顶元素所对应的数组值与数组元素比较,俩个数的较小值减去原来保存的栈顶元素所对应数组值即为接雨水凹槽的高,此时数组下标与栈顶差值减1即为接雨水凹槽的宽,相乘即为所接雨水的面积,保持循环,直到栈为空或者栈为递减,退出循环,进行数组下一个元素比较。

上面思路听起来比较复杂,可以看图理解:

typedef int DateType;
typedef struct  Stack
{DateType* a;int top;int capacity;
}Stack;
//初始化和销毁
void InitStack(Stack* ps)
{assert(ps);ps->a = NULL;ps->top = ps->capacity = 0;
}
void DestroyStack(Stack* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}
//出栈和入栈
void StackPush(Stack* ps, DateType x)
{assert(ps);if(ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 4;DateType* tmp = (DateType*)realloc(ps->a,sizeof(DateType) * newcapacity);if (tmp == NULL){perror("realloc fail:");return;}ps->capacity = newcapacity;ps->a = tmp;}ps->a[ps->top] = x;ps->top++;}
void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}
//栈顶元素和元素个数
int StackSize(Stack* ps)
{assert(ps);return  ps->top;
}
DateType StackTop(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];
}//判空
bool  IsEmptyStack(Stack* ps)
{assert(ps);return ps->top == 0;
}
int MIN(int x, int y)
{return x > y ? y : x;
}
int trap(int* height, int heightSize) {Stack ps;InitStack(&ps);int count = 0;for (int i = 0; i < heightSize; i++){while (ps.top > 0 && height[StackTop(&ps)] < height[i]){DateType tmp = StackTop(&ps);StackPop(&ps);if (ps.top == 0){break;}int h = MIN(height[StackTop(&ps)], height[i]);int width = i - StackTop(&ps) - 1;count += (h - height[tmp]) * width;}StackPush(&ps, i);}DestroyStack(&ps);return count;
}

三、每日温度 

 

 思路:这题思路比较巧妙,运用了单调递减栈和上面一题类似

(1)创造栈用来存放数组元素下标

(2)遍历数组,若栈为空或者栈顶元素所对应的数组值大于等于数组元素,则直接入栈

(3)若栈顶元素所对应数组元素值小于数组元素,则做出判断,将栈顶元素保存,且出栈,由于当前数组元素大于栈顶元素对应数组元素值,而且一定是第一个大于栈顶元素对应数组元素值,直接求出下标差(当前数组元素下标和栈顶元素差)就是二者的距离,放入所求目标数组内(数组下标为保存的栈顶元素)。继续看新的栈顶元素,循环往复,直到当前数组元素小于等于栈顶元素所对应数组值或者栈为空停止,然后将数组元素下标入栈,进行数组下一个元素比较

(3)数组遍历结束后,栈为单调递减栈,里面元素所对应数组值(气温)向后检索找不到比它高的温度,所以以这些栈元素为下标的目标数组元素全部置为0.

图解如下:

typedef int DateType;
typedef struct  Stack
{DateType* a;int top;int capacity;
}Stack;
//初始化和销毁
void InitStack(Stack* ps)
{assert(ps);ps->a = NULL;ps->top = ps->capacity = 0;
}
void DestroyStack(Stack* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}
//出栈和入栈
void StackPush(Stack* ps, DateType x)
{assert(ps);if(ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 4;DateType* tmp = (DateType*)realloc(ps->a,sizeof(DateType) * newcapacity);if (tmp == NULL){perror("realloc fail:");return;}ps->capacity = newcapacity;ps->a = tmp;}ps->a[ps->top] = x;ps->top++;}
void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}
//栈顶元素和元素个数
int StackSize(Stack* ps)
{assert(ps);return  ps->top;
}
DateType StackTop(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];
}//判空
bool  IsEmptyStack(Stack* ps)
{assert(ps);return ps->top == 0;
}int* dailyTemperatures(int* temperatures, int temperaturesSize, int* returnSize) {int *answer=(int *)malloc(sizeof(int)*temperaturesSize);Stack  st;InitStack(&st);for(int i=0;i<temperaturesSize;i++){while(st.top>0&&temperatures[i]>temperatures[StackTop(&st)]){answer[StackTop(&st)]=i-StackTop(&st);StackPop(&st);if(st.top==0){break;}}StackPush(&st,i);}while(st.top>0){answer[StackTop(&st)]=0;StackPop(&st);}* returnSize=temperaturesSize;return answer;}

四、柱状图中最大的矩形 

 

思路:这题思路与接雨水问题一样,不过此题用的是严格单调增栈 

(1)创造栈用来存放数组元素下标

(2)遍历数组,若栈为空或者栈顶元素所对应的柱形高度小于当前柱形高度,则当前柱形高度的数组下标直接入栈

(3)若栈顶元素所对应数组元素值大于等于数组元素,则做出判断,将栈顶元素临时保存,且出栈,再用当前数组元素下标与栈顶元素做差-1即为临时保存的栈顶元素所对应柱形高度的宽,根据原来临时保存栈顶元素求出其对应的高,就可以求出该高度的最大矩形面积,,保持循环,直到栈为空或者栈为严格递增,退出循环,进行数组下一个元素比较。

(4)数组遍历结束,栈为严格单调递增栈,除了最后一个栈底元素外,其他栈元素对应柱形高度最大矩形宽度为数组长度减去当前栈元素左侧一个栈元素的值-1,栈底元素对应柱形高度最大矩形宽度为数组元素长度

注:这里面有几个注意的细节

<1>当栈元素为1个,且数组元素小于等于栈顶对应柱形高度,此时临时保存栈顶元素,出栈,此临时保存栈顶元素对应柱形高度所能扩展做大矩形宽度为:当前数组元素下标i减去临时保存的栈顶元素

<2>数组元素等于栈顶栈顶对应柱形高度时,虽然所求的最大矩形不是这个栈顶的最大矩形,但是要小于这个栈顶元素对应的最大矩形面积,不碍事,直到下一个数组元素严格小于栈顶元素对应柱形高度,此时所求的最大矩形面积即之前那个相等高度的最大矩形面积,所以不影响

图解如下:

typedef int DateType;
typedef struct  Stack
{DateType* a;int top;int capacity;
}Stack;
//初始化和销毁
void InitStack(Stack* ps)
{assert(ps);ps->a = NULL;ps->top = ps->capacity = 0;
}
void DestroyStack(Stack* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}
//出栈和入栈
void StackPush(Stack* ps, DateType x)
{assert(ps);if(ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 4;DateType* tmp = (DateType*)realloc(ps->a,sizeof(DateType) * newcapacity);if (tmp == NULL){perror("realloc fail:");return;}ps->capacity = newcapacity;ps->a = tmp;}ps->a[ps->top] = x;ps->top++;}
void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);ps->top--;
}
//栈顶元素和元素个数
int StackSize(Stack* ps)
{assert(ps);return  ps->top;
}
DateType StackTop(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];
}//判空
bool  IsEmptyStack(Stack* ps)
{assert(ps);return ps->top == 0;
}
int  MAX(int x, int y)
{return x>y?x:y;
}int largestRectangleArea(int* heights, int heightsSize) {Stack st;InitStack(&st);int max = 0;for (int i = 0; i < heightsSize; i++){while (st.top>0 && heights[i] <= heights[StackTop(&st)]){int tmp = StackTop(&st);StackPop(&st);if(st.top==0){max=MAX(max, heights[tmp]*i);break;}int width = i - StackTop(&st) - 1;max = MAX(max, heights[tmp] * width);}StackPush(&st, i);//严格单调增}//遍历结束后,变为严格单调递增栈while (st.top>0){int tmp =StackTop(&st);StackPop(&st);if (st.top==0){max = MAX(max, heights[tmp] * heightsSize);break;}int width = heightsSize - StackTop(&st)-1 ;max = MAX(max, heights[tmp] * width);}return max;}

 总结:本篇文章讲解了单调栈的应用,为系列题目,有利于帮助理解单调栈的用法和这系列问题思路。

希望大家阅读完可以有所收获,同时也感谢各位铁汁们的支持。文章有任何问题可以在评论区留言,百题一定会认真阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/236871.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3D模型人物换装系统(二 优化材质球合批降低DrawCall)

3D模型人物换装系统 介绍原理合批材质对比没有合批材质核心代码完整代码修改总结 介绍 本文使用2018.4.4和2020.3.26进行的测试 本文没有考虑法线贴图合并的问题&#xff0c;因为生成法线贴图有点问题&#xff0c;放在下一篇文章解决在进行优化 如果这里不太明白换装的流程可以…

HarmonyOS引导页登陆页以及tabbar的代码说明1

效果 以下代码是东拼西凑出来的。只是为了个人熟悉一下相关模块的使用&#xff1a; 用的知识点&#xff1a; Resouces 此部分分内容可以在项目中找到&#xff1a; resources/base/element/color.json 为项目着色配置&#xff0c;当然也可以正接在代码里写 float.json 为相关…

IPv6路由基础-理论与配置

在企业网络中&#xff0c;IPv6技术的应用越来越普及。IETF组织针对IPv6网络制定了路由协议OSPFv3。 OSPFv3 ff02::5是为OSPFv3路由协议预留的IPv6组播地址。OSPFv3中的路由条目下一跳地址是链路本地地址。OSPFv3是运行在IPv6网络的OSPF协议。运行OSPFv3的路由器使用物理接口的…

浅析 fuse kernel mmap write 过程及性能问题

前言 最近在项目里面用到了fuse文件系统&#xff0c;在使用过程中遇到了一个内核在做mmap write的一个bug&#xff0c;目前并没有从根本上解决这个bug&#xff0c;而是通过修改fuse kernel module的一些参数&#xff0c;绕开了这个bug。这里记录一下这个问题&#xff0c;并顺便…

手把手教你在windows上安装Portainer

前言 大家好&#xff0c;我是潇潇雨声。在之前的文章中&#xff0c;我们探讨了在 Windows 上安装 Docker 的方法。今天&#xff0c;我将简要介绍一个开源的轻量级容器管理工具——Portainer&#xff0c;它类似于 navicat。Portainer 是一个与 navicat 类似的工具&#xff0c;但…

Amazon Toolkit — CodeWhisperer 使用

tFragment--> 官网&#xff1a;https://aws.amazon.com/cn/codewhisperer/?trkcndc-detail 最近学习了亚马逊云科技的 代码工具&#xff0c;感慨颇多。下面是安装 和使用的分享。 CodeWhisperer&#xff0c;亚马逊推出的实时 AI 编程助手&#xff0c;是一项基于机器学习…

详解数据科学自动化与机器学习自动化

过去十年里&#xff0c;人工智能&#xff08;AI&#xff09;构建自动化发展迅速并取得了多项成就。在关于AI未来的讨论中&#xff0c;您可能会经常听到人们交替使用数据科学自动化与机器学习自动化这两个术语。事实上&#xff0c;这些术语有着不同的定义&#xff1a;如今的自动…

【QT Visual Studio环境配置】error MSB8020: 无法找到 v141/v142 的生成工具(完整版)

首先要了解V**平台工具集根据你安装的Visual Studio版本不同而有所区别&#xff0c;知道这个就容易解决问题了&#xff0c;确定你安装的那个版本&#xff0c;需要使用哪个工具集。 v143–>VS2022v142–>VS2019v141–>VS2017v140–>VS2015v120–>VS2013 一、解决…

机器学习之线性回归(Linear Regression)附代码

概念 线性回归(Linear Regression)是机器学习中的一种基本的监督学习算法,用于建立输入变量(特征)与输出变量(目标)之间的线性关系。它假设输入变量与输出变量之间存在线性关系,并试图找到最佳拟合线来描述这种关系。 在简单线性回归中,只涉及两个变量:一个是自变量…

MySQL:通过官方mysql server,搭建绿色版mysql服务器(Windows)

1. 官网下载mysql server 下载mysql server的zip文件&#xff0c;地址&#xff1a; https://downloads.mysql.com/archives/community/ 解压后 2. 初始化数据库 运行cmd&#xff0c; 进入bin目录&#xff0c;运行 mysqld --initialize-insecureinitialize-insecure说明如…

Jenkins 插件下载速度慢安装失败?这篇文章可能解决你头等难题!

Jenkins部署完毕&#xff0c;如果不安装插件的话&#xff0c;那它就是一个光杆司令&#xff0c;啥事也做不了&#xff01; 所以首先要登陆管理员账号然后点击系统管理再点击右边的插件管理安装CI/CD必要插件。 但是问题来了&#xff0c;jenkins下载插件速度非常慢&#xff0c…

Educational Codeforces Round 160 (Div. 2) A~E

A.Rating Increase&#xff08;思维&#xff09; 题意&#xff1a; 给出一个仅包含数字的字符串 s s s&#xff0c;要求将该字符串按以下要求分成左右两部分 a , b a,b a,b&#xff1a; 两个数字均不包含前导 0 0 0 两个数字均大于 0 0 0 b > a b > a b>a 如果…

算法基础之快速幂

快速幂 核心思想&#xff1a;logk的复杂度求出ak mod p 将k拆成若干个2的n之和 (二进制) #include<iostream>#include<algorithm>using namespace std;typedef long long LL;LL qmi(int a,int k,int p){LL res 1 % p;while(k) //k转为二进制 还有正数 就进行…

U-MixFormer:用于高效语义分割的类unet结构的混合注意力Transformer

论文&#xff1a; 代码&#xff1a;GitHub - RecklessRonan/MuSE 感觉这篇比较优雅无痛涨点欸.....最近要期末了没时间看文章和做实验了&#xff08;摊 摘要 语义分割在Transformer架构的适应下取得了显著的进步。与Transformer的进步并行的是基于CNN的U-Net在高质量医学影…

QT基础介绍

QT介绍 QT 是跨平台的c开发库&#xff0c;主要用来开发图形用户界面&#xff08;Graphical User Interface&#xff0c;GUI&#xff09;程序&#xff0c;当然也可以开发不带界面的命令行&#xff08;command user interface&#xff0c;CUI&#xff09;程序。 Qt中文官网&…

互操作性(Interoperability)如何影响着机器学习的发展?

互操作性&#xff08;Interoperability&#xff09;&#xff0c;也称为互用性&#xff0c;即两个系统之间有效沟通的能力&#xff0c;是机器学习未来发展中的关键因素。对于银行业、医疗和其他生活服务行业&#xff0c;我们期望那些用于信息交换的平台可以在我们需要时无缝沟通…

mt5和mt4交易软件有什么区别?

MetaTrader 4&#xff08;MT4&#xff09;和MetaTrader 5&#xff08;MT5&#xff09;是两种广泛使用的外汇和金融市场交易平台&#xff0c;由MetaQuotes公司开发。尽管它们都是外汇交易的常见选择&#xff0c;但在功能和特性上存在一些区别。以下是MT4和MT5之间的主要区别&…

python三大开发框架django、 flask 和 fastapi 对比

本文讲述了什么启发了 FastAPI 的诞生&#xff0c;它与其他替代框架的对比&#xff0c;以及从中汲取的经验。 如果不是基于前人的成果&#xff0c;FastAPI 将不会存在。在 FastAPI 之前&#xff0c;前人已经创建了许多工具 。 几年来&#xff0c;我一直在避免创建新框架。首先&…

Educational Codeforces Round 160 (Rated for Div. 2) A~C

目录 A. Rating Increase 题目分析&#xff1a; B. Swap and Delete 题目分析: C. Game with Multiset 题目分析: A. Rating Increase 题目分析&#xff1a; 因为首部不为零&#xff0c;故我们从第二个字符开始遍历&#xff0c;如果遇到第一个不为‘0’的字符&#xff0…

C#文件操作(一)

一、前言 学习心得&#xff1a;C# 入门经典第8版书中的第20章《文件》 二、操作文件的相关类 在C#应用程序中Syste.IO名称空间包含用于在文件中读写数据的类。在此我列举一下File、Directory、Path、FileInfo、DirectoryInfo、FileSystemInfo、FileSystemWatcher。其中在Syste…