文章目录
Leetcode :150.逆波兰表达式求值
题目描述
给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
有效的算符为 ‘+’、‘-’、‘*’ 和 ‘/’ 。
每个操作数(运算对象)都可以是一个整数或者另一个表达式。
两个整数之间的除法总是 向零截断 。
表达式中不含除零运算。
输入是一个根据逆波兰表示法表示的算术表达式。
答案及所有中间计算结果可以用 32 位 整数表示。
示例
示例 1:
输入:tokens = [“2”,“1”,“+”,“3”,“*”]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:
输入:tokens = [“4”,“13”,“5”,“/”,“+”]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:
输入:tokens = [“10”,“6”,“9”,“3”,“+”,“-11”,““,”/“,””,“17”,“+”,“5”,“+”]
输出:22
解释:该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
思路分析
由题意可知,tokens为一个存储string对象的容器,我们可以对tokens遍历,如果遇到操作数就入栈,如果遇到操作符就取连续的两个栈顶数据与该操作符运算,并将该结果入栈。当遍历完成后,就说明逆波兰表达式已经计算完毕,此时栈中只剩下一个式子结果。
注意:
1:swich中的参数可以使用字符整型来进行循环判断。
2:在进行运算时,数字字符是不能进行运算的,所以我们可以使用stoi函数将数字字符转换为数字进行运算。
代码实现
class Solution{
public:
int evalRPN( vector<string>& tokens)
{
stack<int> st;
for( auto& str : tokens )
{
if( str == "+" || str == "-" || str == "*" || str == "%")
{
int right = st.top();
st.pop();
int left = st.top();
st.pop;
switch( str[0])
{
case '+':
st.push( left + right );
break; //注意添加break;
case '-':
st.push( left - right );
break; //注意添加break;
case '*':
st.push( left * right );
case '/':
st.push( left / right );
}
}
else
{
st.push(stoi(str));
}
}
//出了循环之后,就说明逆波兰表达式中操作数与操作符都运算完毕,此时栈中只剩下一个结果。
return st.top();
}
}
Leetcode: 155.最小栈
题目描述
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack 类:
MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。
示例
示例 1:
输入: [“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]输出: [null,null,null,null,-3,null,0,-2]
思路分析
目标:我们要保持最小栈的栈顶为当前栈的最小值。
在MinStack中我们可以增加自定义成员最小栈,这个栈存储的是小于等于_minst.top的值。
入栈时:栈先正常入栈,如果最小栈为空 或者 val 小于等于最小栈的栈顶 ,因为我们要存的是当前栈的最小值(记住,两个判断条件不能相反,因为调用top()时栈不为空),val就在辅助栈中入栈。
出栈时:如果正常栈的栈顶和最小的相同,辅助栈出栈,栈出栈.否则的话,辅助栈不出栈,栈正常出栈。
求最小值:获取当前最小栈的栈顶就可以获取当前栈的最小值。
代码实现
class MinStack {
public:
void push(int val) {
_st.push(val);
if( _minst.empty() || val <= _minst.top())
_minst.push(val);
}
void pop() {
if( !_st.empty() && _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;
};
牛客:JZ231.栈的压入,弹出序列
题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。
- 0<=pushV.length == popV.length <=1000
- -1000<=pushV[i]<=1000
- pushV 的所有数字均不相同
示例
示例1
输入: [1,2,3,4,5],[4,5,3,2,1] 返回值:true 说明:
可以通过push(1)=>push(2)=>push(3)=>push(4)=>pop()=>push(5)=>pop()=>pop()=>pop()=>pop() 这样的顺序得到[4,5,3,2,1]这个序列,返回true
示例2
输入:
[1,2,3,4,5],[4,3,5,1,2]
复制
返回值:false
复制
说明:
由于是[1,2,3,4,5]的压入顺序,[4,3,5,1,2]的弹出顺序,要求4,3,5必须在1,2前压入,且1,2不能弹出,但是这样压入的顺序,1又不能在2之前弹出,所以无法形成的,返回false
思路分析
1:我们可以创建一个辅助栈st,首先遍历pushV栈,将pushV栈中的数据依次入栈到辅助栈中。
2: 在这个过程中,如果 popV中下标为popi的数据:与辅助栈的栈顶相同,我们便可以出栈。但是,在st栈中,可能会有多个数据符合这个条件,而这个行为我们可以采用循环。
3: 如果不符合st出栈的条件,则继续遍历pushV,st继续入栈。
4: 当遍历完pushV之后,如果st为空,就说明出栈顺序与入栈顺序相匹配,否则,就不匹配。
例如:
popV的遍历到时,此时st的栈顶为4,不符合条件,所以st将数据5入栈。等再次遍历的时候吗,st每一次出栈,栈顶都与popV中下标为popi中的数据相同。
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
stack<int> st;
int popi = 0;
for ( const auto& pushVal : pushV )
{
st.push( pushVal );
while ( !st.empty() && popV[popi] == st.top() )
{
st.pop();
++popi;
}
}
return st.empty();
}
};