第二周第六天|力扣20、有效的括号 1047、删除字符串中所有相邻重复项 150、逆波兰表达式求值

20、有效的括号

思路:有效的括号这道题目,是要判断当前的括号是否能够生效,这种题目的关键是要分析好情况,也就是何时不生效。对于匹配类问题,其实本质可以看成是消除类问题,是栈的拿手好戏。

有三种情况:
1、左括号多余,表现为当指针扫描完字符串时,栈非空
2、类型不匹配,当指针指向的右括号和栈中的栈顶元素不相同时,类型不匹配。
3、右括号多余,当指针扫描到右括号时,栈已空

这三种情况包含了所有不生效的情况,因此接下来代码就不那么难了。

总结:遇到匹配类问题,考虑使用栈

代码:

class Solution {
public:
    bool isValid(string s) {
        stack<char>st;
        for(int i=0;i<s.size();i++){
            if(s[i]=='('){
                st.push(')');
            }
            else if(s[i]=='['){
                st.push(']');
            }
             else if(s[i]=='{'){
                st.push('}');
            }
            else if(st.empty()||s[i]!=st.top()){
                return false;
            }
            else{
                st.pop();
            }
        }
        return st.empty();
    }
};

注意细节:字符串的比较,比较字符常量时加的是单引号,比较字符串常量时加的是双引号,当然比较字符串常量的时候,字符串常量可以包含多个字符,也可以包含0个字符。

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

思路:消除相邻重复项,消除类问题,这是栈的拿手好戏,考虑用stack。

这道题目要求输出的结果唯一,以常理来考虑,删除重复项不应该改变字符串的顺序,而栈的特性是先进后出,因此如果用栈的话最后把栈取出来后还要再翻转一下,如果用字符串来模拟栈的话,直接输出字符串就可以了,不需要再翻转,因此本题用string能方便一些。(需要理解是拿string来模拟栈)

当读取到原字符串中的元素和辅助字符串中的最后一个元素相同时,取出辅助字符串的最后一个元素,当辅助字符串为空或者原字符串的元素和辅助字符串的最后一个元素不同时,将该字符压入辅助字符串中,最后返回辅助字符串即为所求。

总结:碰到消除类问题,考虑使用栈,但是碰到具体问题的时候可以更灵活一些,例如本题就可以用字符串来模拟栈,从而省去了翻转的操作。

代码:

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

注意细节:注意字符串的弹出,弹出的是最后一个元素。

150、逆波兰表达式求值

背景知识:逆波兰表达式的缩写是RPN,全称是reverse polish notaion,它的本质是后缀表达式,用数据结构来实现的话和树的后序遍历是等价的(其中运算符作为中间节点)。

思路:虽然后缀表达式可以用树的后序遍历来模拟,但这道题目的实现并不需要用到树,我们来分析一下,*对于( 1 + 2 ) * ( 3 + 4 ),它的后缀表达式12+34+看上去可能没有那么美观,但是可以发现,在使用后缀表达式计算的时候,我们不需要给表达式加括号,这是一个巨大的优势,可以省去计算机的许多判断逻辑。

实现计算的步骤:
1、当读到数字时,将读到的数字压入栈中
2、当读到运算符时,弹出栈顶的两个数字进行运算,这里需要注意,由于栈的先进后出的特性,先进去的数字反而应该作为左操作数,后进去的数字才应该作为右操作数,这里不要弄反了。接着将结果压回栈中,继续扫描表达式直到结束,返回栈中元素,正确的结果应该时唯一的,也就是栈中只有一个元素。

总结:这道题目是考察计算机计算本质的好题,重点是要理解后缀表达式可以不加括号的好处以及栈的先进后出的特性使得先进去的数字应该作为左操作数,后进去的数字才是右操作数,明确了这两点和计算的步骤后,代码就不难写了。

代码:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<long long>st;//栈非常擅长解决这种消除类问题
        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(stoll(tokens[i]));
            }
        }
            int result=st.top();
            st.pop();
            return result; 
  }
};

补充:stoll是将字符转换成long long int(长整型)的函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值