当前位置: 首页 > news >正文

刷题记录(10)stack和queue的简单应用

一、最小栈

155. 最小栈 - 力扣(LeetCode)

怎么说呢,其实push pop top直接套STL库的就行,其实最麻烦的就是如何获得堆栈中最小的元素(而且硬性要求常数时间解决),毕竟我们非常清楚,栈是不能随意访问元素的,至多只能访问栈顶元素。

其实在打这句话的时候我就想到了一个解决方法,虽然我们不能随意的访问元素,但是push的时候我们可以接触到每个元素,只要记录下来最小的不就完了:

但是画着画着就出现问题了,如果在目前这一步连续pop两次,也就是把-2全部pop出去,那你栈里最小不就变0了嘛,这个时候你的min受影响的啊,也就是pop以后也必须检查并修改min的值。

于是,再来一个栈:

需要注意的点就是如果检测到minst的栈顶和此次push进st的值一样我们也得push到minst里。

其实是倒过来推的,如果st需要pop-2,我们为了维护最小值,肯定得检测检测minst栈顶和它相等不等,相等也得pop,所以就得出来如果此次往st中push的值跟minst的top相等,也得push到minst里。

class MinStack {
public:MinStack() {}void push(int val) {st.push(val);if(minst.empty())minst.push(val);else if(val <= minst.top())minst.push(val);}void pop() {if(minst.top() == st.top())minst.pop();st.pop();}int top() {return st.top();}int getMin() {return minst.top();}
private:stack<int> st;stack<int> minst;
};

直接通过了,需要说的是默认构造函数,我们说过,所有非静态成员变量一定走初始化列表,那么我们两个成员栈也都需要走初始化列表,我们还说过:

①初始化列表给值的以初始化列表的值初始化

②初始化列表没给值有缺省值的按缺省值走初始化列表

③走不了初始化列表初始化的,编译器对于内置类型的初始化可能是随机值也可能是0之类的值;对于自定义类型调用它们的默认构造函数,没有默认构造的报错

好了好了,不用背书了,所以这里我们的默认构造啥都没写就是这个道理,没有显式初始化的走自定义类型的默认构造。

这道题的重点就是从存到一个变量min里转变到存到一个栈里预防pop造成的负面效果。

二、栈的压入、弹出序列

栈的压入、弹出序列_牛客题霸_牛客网

等于给你两个序列,一个序列代表压栈顺序,一个序列代表出栈顺序,让你判断出栈序列合理不合理。

这道题其实有点像思路实现,我自己想的昂,毕竟咱们人碰见这个题咋做,就说这个序列:

看见第一个出的是4,所以入的时候肯定是1234入进去了,出了个4,然后发现下一个是5,那就入5出5,再连着出刚好就是这个序列。

参数不是这俩嘛。

可以设计一个栈,让它入到popV的第一个数再停,然后开始遍历popV,每次比较栈顶元素是否和popV此次遍历的数相同,如果不相同,先看看push完了没,没有push完就疯狂的push直到碰见popV遍历到的数。如果相同直接pop再继续检查下一个应该pop的值。

到这就不用再演示了。

但是看题目的意思估计俩序列里的数不会不一样,顶多次序不合理,先不考虑俩序列不一样吧,那以上就是我们全部的思路,其实说思路,也就是把我们做选择题的做法转换成一句句代码表达出来。

序列不合理就是遍历的时候遍历到不一样的。

序列合理就是遍历完了也没出事的。

代码出现过两个问题:

class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param pushV int整型vector* @param popV int整型vector* @return bool布尔型*/bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {// write code herestack<int> st;st.push(pushV[0]);//先push到与popV[0]相同 size_t i = 1;while (i <= pushV.size() && st.top() != popV[0])st.push(pushV[i++]);//遍历popV check st.top() ? popV[j]//== pop; j++//!= check i ? pushV.size()->push完毕false,未push完毕,while pushsize_t j = 0;while (j < popV.size()){if (st.top() == popV[j++])st.pop();else if (i < pushV.size())while (i <= pushV.size()&& st.top() != popV[j])st.push(pushV[i++]);elsereturn false;}return true;}
};

第一次发现的错误点在:

只要进循环就得判断条件,把++写到判断条件可能造成:

j遍历到5了,很明显按说该走第二个条件,但是第一个条件判断完以后j就变成指向3的了,直接死翘翘了。

第二次错误点就是,我在刚创建好st就先push就是怕栈空,结果到while里就不管了,第一个if赤裸裸直接st.top(),第二个else if也差不多没遍历完的往里进里层的while也是不管栈空不空,直接往上st.top()。

除此之外就只是我们正常做选择的正常思路。

三、用两个栈实现队列

232. 用栈实现队列 - 力扣(LeetCode)

文艺复兴昂,只不过是以C++的形式,今非昔比了。

一个栈用来压数据,如果调pop或者peek(front)接口,那就把pushst依次全部入到popst,至于empty,俩栈都不为空队列就不为空。

class MyQueue {
public:MyQueue() {}void push(int x) {pushst.push(x);}int pop() {int ret;if(!popst.empty()){ret = popst.top();popst.pop();}else{while(!pushst.empty()){popst.push(pushst.top());pushst.pop();}ret = popst.top();popst.pop();}return ret;}int peek() {if(!popst.empty())return popst.top();else{while(!pushst.empty()){popst.push(pushst.top());pushst.pop();}return popst.top();}}bool empty() {return pushst.empty()&&popst.empty();}
private:stack<int> pushst;stack<int> popst;
};

需要强调的就是如果popst不为空的话

pop时优先pop和peek popst的值,真没值了再从pushst中拷贝。

四、逆波兰表达式求值

150. 逆波兰表达式求值 - 力扣(LeetCode)

大概搜了一下这个逆波兰表达式,主要作用就是因为计算机底层如果需要读优先级和括号,就降低运算的效率。

我们一般用的叫中缀表达式,而逆波兰表达式其实是后缀表达式,把运算符放到两个运算数后,读到运算符以后就把前面的两个运算数带入:

大概意思就是这样的,其实理解了后缀表达式之后很容易想到,直接用栈就行,如果读到运算符,那就弹出栈顶的两个数,如果读到数就入栈,也就是:

并且需要注意的是,第一个弹出来的是右操作数,第二个弹出来的是左操作数,+ *我不挑你的理,假如- /呢?

12 - -11和-11 - 12

6 / 3 和3 / 6

所以一定得顾好左操作数和有操作数的顺序。

另外读典例和输入我注意到,如果直接以string[0]=="+" "-" "*" "/"为判断条件,负数的符号将会被错误辨别,因此还得注意判断string的长度来判断这到底是一个负数的负号还是一个减号。

class Solution {
public:int evalRPN(vector<string>& tokens) {stack<int> st;for(auto& e: tokens){if((e[0] == '+'||e[0] == '-'||e[0] == '*'||e[0] == '/')&&e.size() == 1){int right = st.top();st.pop();int left = st.top();st.pop();switch (e[0]){case '+':st.push(left + right);break;case '-':st.push(left - right);break;case '*':st.push(left * right);break;case '/':st.push(left / right);break;default:break;}}elsest.push(stoi(e));}return st.top();}
};

如果这道题要求先拆成后缀表达式然后再计算,那可就要了老命了,如果只计算,那就是充分利用stack的特性保证运算顺序即可。

没啥可说的,唯一用了个stoi查了查库,其它的就是图咋画,代码咋写。

第一个参数传需要转换的string对象,这个不用解释;

第二个参数idx是个指针变量,如果你想知道str在哪里开始不能再转换成数字的第一个字符的地址,那就传一个指针变量,这个函数就会把这个地址存到这个指针变量上;

最后一个参数是,str里的数字字符以多少进制的方式转换。

测试代码,直接扣的库里面的:

五、数组中的第K个最大元素

215. 数组中的第K个最大元素 - 力扣(LeetCode)

经典的top-k问题,用堆解决,或者换句话来说,用priority-queue来解决:

class Solution {
public:int findKthLargest(vector<int>& nums, int k) {priority_queue<int> pq(nums.begin(),nums.end());for(int i = 0;i < k - 1;i++)pq.pop();return pq.top();}
};

只不过不要前k个,只要第k个。

http://www.dtcms.com/a/390295.html

相关文章:

  • 如何进行时间管理?
  • Spring面试题及详细答案 125道(46-65) -- 事务管理
  • OA ⇄ CRM 单点登录(SSO)实现说明
  • 人工智能在设备管理软件中的应用
  • __pycache__ 文件夹作用
  • 利欧泵业数据中心液冷系统解决方案亮相2025 ODCC开放数据中心峰会
  • 【论文阅读】Masked Conditional Variational Autoencoders for Chromosome Straightening
  • 天气预测:AI 如何为我们 “算” 出未来的天空?
  • 大数据管理与应用有什么注意事项?企业该如何发挥大数据的价值
  • CSS的opacity 属性
  • STM32 LwIP协议栈优化:从TCP延迟10ms降至1ms的内存配置手册
  • 【0基础3ds Max】创建标准基本体(长方体、球体、圆柱体等)理论
  • 驾驭未来:深度体验 Flet 0.7.0 的重大变革与服务化架构
  • 【Datawhale组队学习202509】AI硬件与机器人大模型 task01 具身智能基础
  • Go语言高并发编程全面解析:从基础到高级实战
  • leetcode算法刷题的第三十八天
  • RHEL 兼容发行版核心对比表
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘yaml’ 问题
  • 无刷电机有感方波闭环控制
  • 【EKL】
  • 设计模式-模板方法模式详解(2)
  • 算法(一)双指针法
  • C语言指针深度解析:从核心原理到工程实践
  • hsahmap的寻址算法和为是你扩容为2的N次方
  • ​​[硬件电路-243]:电源纹波与噪声
  • Kurt-Blender零基础教程:第1章:基础篇——第2节:认识界面
  • Kurt-Blender零基础教程:第1章:基础篇——第1节:下载与键位
  • 袋鼠参谋 - 美团推出的餐饮行业经营决策 AI 助手
  • 09-Redis 哈希类型深度解析:从命令实操到对象存储场景落地
  • 【论文阅读】MaskGIT: Masked Generative Image Transformer