本文主要讲解C++中stack和queue的一些OJ题目
文章目录
- 1、[最小栈](https://leetcode.cn/problems/min-stack/)
- 2、[栈的压入、弹出序列](https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId=13&&tqId=11174&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking)
- 3、[逆波兰表达式](https://leetcode.cn/problems/evaluate-reverse-polish-notation/)
- 4、[用队列实现栈](https://leetcode.cn/problems/implement-stack-using-queues/submissions/)
1、最小栈
思路1:
使用两个栈,st用来进行常规的入栈操作。minst栈也同步进行,但是有要求,该栈主要负责返回最小值。当minst为空或者val比minst栈顶元素小才入栈。当minst的栈顶元素和st的栈顶栈
代码如下:
class MinStack {
public:
MinStack() {
}
void push(int val)
{
if(minst.empty() || minst.top() >= val)
{
minst.push(val);
}
st.push(val);
}
void pop()
{
if(st.top() == minst.top())
{
minst.pop();
}
st.pop();
}
int top()
{
return st.top();
}
int getMin()
{
return minst.top();
}
private:
stack<int> st;
stack<int> minst;
};
但是,当全部元素相同时,我们的空间复杂度是O(N)了。这时,我们可以将最小栈设计成结构体,结构体里面存储的是元素的值和个数。
思路2:
为了解决元素相同时,消耗内存。和方法思路一样,只是此时入栈的是一个结构体数据。{1,12},1表示数据,12表示出现的次数
class MinStack {
public:
MinStack() {
}
void push(int val)
{
if(_minst.empty())
{
Data d;
d._val = val;
d._count++;
_minst.push(d);
}
else if(_minst.top()._val == val)
{
_minst.top()._count++;
}
else if(_minst.top()._val >= val)
{
Data d;
d._val = val;
d._count++;
_minst.push(d);
}
_st.push(val);
}
void pop()
{
if((_minst.top()._val == _st.top()) && _minst.top()._count > 1)
{
_minst.top()._count--;
}
else if((_minst.top()._val == _st.top()) && _minst.top()._count == 1)
{
_minst.pop();
}
_st.pop();
}
int top()
{
return _st.top();
}
int getMin()
{
return _minst.top()._val;
}
private:
stack<int> _st;
//定义一个结构体,当入栈时候,入的是一个结构体[{1,12}],表示1有12个
struct Data
{
int _val = 0;
int _count = 0;
};
stack<Data> _minst;
};
2、栈的压入、弹出序列
代码如下:
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV)
{
stack<int> st;
int pushi = 0,popi = 0;
//遍历pushV进行入栈操作
while(pushi < pushV.size())
{
//入栈
st.push(pushV[pushi++]);
//和比较popV[]比较进行出栈操作
while(!st.empty() && st.top() == popV[popi])
{
st.pop();
popi++;
}
}
return st.empty();
}
};
3、逆波兰表达式
注意:逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 )
该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * )
逆波兰表达式主要有以下两个优点:
1.去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
2.适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
class Solution {
public:
int evalRPN(vector<string>& tokens)
{
stack<int> st;
for(auto& str : tokens)
{
if(!(str == "+" || str == "-" || str == "*" || str == "/"))
{
st.push(stoi(str)); //操作数转化为整形入栈
}
else
{
//操作符取栈顶的两的元素出栈进行运算,先是右操作数,再是左操作数
int right = st.top();
st.pop();
int left = st.top();
st.pop();
int ret;
switch(str[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;
}
}
}
return st.top();
}
};
4、用队列实现栈
思路:定义两个栈,q1和q2。其中q1用于存储栈的元素,q2用于辅助操作。
具体实现方法是:在每次压入元素时,将元素先插入到q2的队尾,然后将q1中的所有元素依次弹出并插入到q2中,最后将q1和q2交换。这样,每次操作后,q1中的队头元素就是最后一个压入的元素,也就是栈顶元素。在弹出元素时,直接从q1中弹出队头元素即可。在获取栈顶元素时,直接返回q1中的队头元素即可。在判断栈是否为空时,只需要检查q1是否为空即可。
class MyStack {
public:
queue<int> q1 ,q2;
MyStack() {}
void push(int x) {
q2.push(x);
while(!q1.empty())
{
q2.push(q1.front());
q1.pop();
}
swap(q1,q2);
}
int pop() {
int front=q1.front();
q1.pop();
return front;
}
int top() {
int front=q1.front();
return front;
}
bool empty()
{ return q1.empty();}
};