栈和队列 part02:20. 有效的括号,1047. 删除字符串中的所有相邻重复项,150. 逆波兰表达式求值

20. 有效的括号

题目

在这里插入图片描述

思考历程

把左括号放到栈里,如果遇到右括号,就与预期的右括号对比。

解题方法(相邻两个括号配对就消除)

巧妙:遇到左括号时,把预期的右括号放到栈里(简化了比较流程)

只需要比较当前元素和栈顶相不相等,比左括号先入栈代码实现要简单得多

  • 流程
  1. 遍历字符串
  2. 如果是左括号:就把相应的右括号入栈
  3. 如果是右括号:就判断三种异常情况:
  • 左括号多了(遍历完才知道)
  • 匹配失败(未遍历完,待检测元素与栈顶元素不相等)
  • 右括号多了(未遍历完,栈里已空)
    在这里插入图片描述
  1. 正常情况:待检测元素与栈顶元素相等,匹配成功

难点

犯错:匹配成功后,记得弹出(消消乐)
犯错:判断判断栈是否为空,要在判断元素是否等于栈顶之前(空栈无栈顶,会出错)

代码

class Solution {
public:
    bool isValid(string s) {
        stack<int>sta;
        if(s.size()%2!=0){
            return false;
        }
        for(int i = 0; i<s.size(); i++){
            //左括号决定入栈
            if(s[i] == '(') sta.push(')');
            else if(s[i] == '{') sta.push('}');
            else if(s[i] == '[') sta.push(']');            
            else if(sta.empty()) return false;//情况三:右括号多了
            else if(s[i] != sta.top()) return false;//情况二:右括号和左括号匹配失败
            else sta.pop();//匹配成功,要弹出            
        }
        return sta.empty();//情况一:左括号多了

    }
};

1047. 删除字符串中的所有相邻重复项

题目

在这里插入图片描述

匹配问题都是栈的强项

思考历程

像消消乐一样。

解题方法(相邻两个字母相等就消除)

  • 巧妙:拿字符串直接作为栈(对字符串进行push_back和pop_back,因为本题要返回修改后的字符串,所以这样做省去了栈转字符串)
  • 流程:
    1、新建接收结果的字符串 result
    2、遍历字符串元素i,如果result为空,或者i与栈顶不匹配,就把i“进栈”
    3、如果匹配上了,就把栈顶弹出
    4、最后返回result字符串

难点

  1. 何时能把字符串作为栈:在字符串的尾部添加字符(进栈),并从尾部删除字符(出栈),同时通过back方法访问栈顶元素,就像栈的操作一样。
  2. string和vector类似,有尾部操作方法push_backpop_back,没有对应的头部操作方法。
  3. string是一个字符序列容器,其中每个元素都是一个char字符。

代码

class Solution {
public:
    string removeDuplicates(string s) {
        string result;
        for(char i:s){
            if(result.empty()||i!=result.back()){
                result.push_back(i);
            }
            else result.pop_back();
        }
        return result;
    }
};

150. 逆波兰表达式求值

题目

在这里插入图片描述

解题方法(运算符+栈顶两个数)

流程:

  1. 遍历字符串
  2. 如果是数字,就入栈
  3. 如果是运算符,就把栈顶的两个元素弹出来运算,然后把结果入栈
  4. 最后的栈顶st.top()就是结果

难点

  1. 犯错:减法、除法有顺序要求,是老元素-新元素,而nums2才是老元素
  2. 犯错:string强制转int出错,要用到stoi函数

代码

class Solution {
public:
    stack<int>st;
    int evalRPN(vector<string>& tokens) {
        for(int i=0; i<tokens.size(); i++){
            if(tokens[i]=="+"||tokens[i]=="-"||tokens[i]=="*"||tokens[i]=="/"){
                int nums1 = st.top();
                st.pop();
                int nums2 = st.top();
                st.pop();
                if(tokens[i]=="+"){
                    st.push(nums2+nums1);
                }
                if(tokens[i]=="-"){
                    st.push(nums2-nums1);
                }
                if(tokens[i]=="*"){
                    st.push(nums2*nums1);
                }
                if(tokens[i]=="/"){
                    st.push(nums2/nums1);
                }                     
            }
            else{
                st.push(stoi(tokens[i]));
            }
        }
        return st.top();

    }
};

栈的三道题总结(相邻匹配)

栈擅长处理的情况:相邻匹配
1、相邻匹配的左、右括号({}),就消除
2、相邻的相同小写字母abba,就消除
3、相邻的两个数字及一个运算符(12+34+*),就执行运算

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值