1. 最小栈
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 minStack = new MinStack(); minStack.push(-2);
minStack.push(0); minStack.push(-3); minStack.getMin(); --> 返回 -3.
minStack.pop(); minStack.top(); --> 返回 0. minStack.getMin();
–> 返回 -2.
思路: 我们可以设定两个栈,一个存放val元素,另一个存放val元素中的最值。
 在val值入栈时我们需要注意的是,当_minstr 栈为空时需要将val入栈。当_minstr栈顶的值大于要插入的val时入栈。
 在删除栈中的值时需要注意的是,_minstr中最小值出现重复的值,也需要删除。
#include<stack> 
class MinStack {
public:
    MinStack() {
    }
    
    void push(int val) {
    _str.push(val);
    if(_minstr.empty() || val <= _minstr.top())
    {
        _minstr.push(val);
    }
    }
    
    void pop() {
        if(_str.top()== _minstr.top())
        {
            _minstr.pop();
        }
        _str.pop();
    }
    
    int top() {
    return _str.top();
    }
    
    int getMin() {
       return _minstr.top();
    }
    stack<int> _str;
    stack<int> _minstr;
};
 
2. 栈的压入、弹出序列
JZ31 栈的压入、弹出序列
描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列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 的所有数字均不相同
 
思路:设置双指针,第一指针指向入栈序列的开始位置,第二个指向出栈序列中的开始位置。设置一个类型为int的栈对象,遍历入栈序列,将pushi指向的位置入栈, 再判断栈顶元素是等于出栈序列popi指向的数据,若是等于便popi自增并删除栈顶元素。
 如图:
 
#include <stack>
class Solution {
public:
    bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
       int pushi = 0;
       int popi = 0;
       stack<int> str;
       while(pushi <pushV.size())
       {
        str.push(pushV[pushi++]);
        while(!str.empty() && str.top() == popV[popi])
        {
            ++popi;
            str.pop();
        }
       }
       return str.empty();
    }
};
 
3.逆波兰表达式求值
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
思路:逆波兰表达式就是中缀表达式。我们这里需要建立一个栈 ,将题目中会出现的符号放入set集合中。遍历vector中的数据 ,判断str中的数据是否为符号,若不是就将数字入栈,若是取出栈顶的数据为右运算数,再取一个作为左运算数,不要忘记对栈顶元素进行删除。利用switch判断vector首元素是否存在并符合case的情况。
class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> s;
        set<string> s1 = {"+","-","*","/"};
        for(auto& str : tokens)
        {
            if(s1.find(str) != s1.end())
            {
                int right = s.top();
                s.pop();
                int left = s.top();
                s.pop();
                switch(str[0])
                {
                    case '+':
                    s.push(left+right);
                    break;
                    case '-':
                     s.push(left-right);
                    break;
                    case '*' :
                     s.push(left*right);
                    break;
                    case '/' :
                     s.push(leftright);
                    break;
                }
            }
            else
            {
                s.push(stoi(str));
            }
        }
        return s.top();
    }
};
                

















