当前位置:   article > 正文

LeetCode第 224 题:基本计算器(C++)_leetcode 224

leetcode 224

224. 基本计算器 - 力扣(LeetCode)
在这里插入图片描述

典型的利用栈应用,注意减号不满足结合律。

利用双栈处理表达式的思路:

通过两个栈来实现:其中一个保存操作数,另一个是保存运算符。从左向右遍历表达式,当遇到数字,就直接压入操作数栈;当遇到运算符,就与运算符栈的栈顶元素进行比较:

  • 如果比运算符栈顶元素的优先级高,就将当前运算符压入栈;
  • 如果比运算符栈顶元素的优先级低或者相同,从运算符栈中取栈顶运算符,从操作数栈的栈顶取 2 个操作数,然后进行计算,再把计算完的结果压入操作数栈,继续比较。

这儿注意括号的处理,当遇到左括号,就压入运算符栈,如果碰到右括号,则从操作数弹出两个元素,从运算符栈弹出一个操作符进行计算,并将结果加入到操作数栈中,重复这步直到遇到左括号。

这题中,因为只有加号和减号,所以只要碰到操作符,就从操作数里弹出两个操作数进行处理,也就是省去了优先级比较的步骤。

另外还要注意栈先进后出的特点,注意操作数的顺序,以及数字的累加(char类型到int的转化,以及个位十位转化)

其实括号放在哪个栈的可以,难点在于代码逻辑处理以及边界条件判断。

class Solution {
public:
    int calculate(string s) {
        stack<int> num;
        stack<char> op;
        int tmp = -1;
        for(const auto &c : s){
            // 空格直接忽略
            if(c == ' ')   continue;
            // 是数字的时候,入栈需要累加之后再入栈
            // 再遇到操作符之前,这个数字就还没有结束
            if(isdigit(c)){
                if(tmp == -1)
                    tmp = c - '0';
                else
                // 此时c是char类型,要先转化为int才能push
                    tmp = tmp * 10 + (c - '0');
            }else{
                    // 进入else代表此时的 c 不是数字了,而它之前的数字已经累加完成
                    // 将累加完成的数字入栈
                    if(tmp != -1){
                        num.push(tmp);
                        tmp = -1;
                    }

                    // 下面对此时的 c 进行处理,c 可能为操作符或者括号:
                    if( c == '+' || c == '-'){
                        while(!op.empty()){
                            if(op.top() == '(')
                                break;
                            // 运算开始
                            int num1 = num.top(); num.pop();
                            int num2 = num.top(); num.pop();
                            if(op.top() == '+'){
                                num.push(num2 + num1);
                                op.pop();
                            }else{
                                // 注意是num2 - num1(顺序)
                                num.push(num2 - num1);
                                op.pop();
                            }
                        }
                        // 运算符入栈
                        op.push(c);
                    }else if(c == '('){
                        // 左括号直接入栈
                        op.push(c);
                    }else{
                        // c 是右括号,一直运算到碰到左括号
                        while(op.top() != '('){
                            int num1 = num.top(); num.pop();
                            int num2 = num.top(); num.pop();
                            if(op.top() == '+'){
                                num.push(num2 + num1);
                                op.pop();
                            }else{
                                // 注意是num2 - num1(顺序)
                                num.push(num2 - num1);
                                op.pop();
                            }
                        }
                        // 运算结束,弹出左括号
                        op.pop();
                    }
            } 
        }
        // 字符串末尾如果是数字,那么最后一个数字也需要入栈,如果是括号,就不需要
        if(tmp != -1)
            num.push(tmp);
        // 处理最后栈中的数据
        while(!op.empty()){
            int num1 = num.top(); num.pop();
            int num2 = num.top(); num.pop();
            if(op.top() == '+'){
                num.push(num2 + num1);
                op.pop();
            }else{
                // 注意是num2 - num1(顺序)
                num.push(num2 - num1);
                op.pop();
            }
        }
        return num.top();
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85

这一题只有加减运算,可以简化一下,首先全部转化为加法,使用一个sign记录符号位即可。所以我们只需要累加 sign*数字 就可以了。从左往右遍历:

  • 是数字:记下当前的数字,即为当前结果
  • 是 + :sign置为1
  • 是 - :sign置为-1
  • 是 ( :当前累加结果入栈,当前符号入栈(两次入栈)
  • 是 ) :两次出栈得到符号位和数字,进行计算

只用一个栈就可以了:

class Solution {
public:
    int calculate(string s) {
        stack<int> stk;
        int res = 0, sign = 1, n = s.size();//sign代表正负,是后续计算元素的符号
        for(int i = 0; i < n; ++i){
            char c = s[i];
            if(isdigit(c)){
                int cur = c - '0';
                while(i != n-1 && isdigit(s[i+1])){//下一个也是数字
                    ++i;
                    int v = s[i] - '0';
                    cur = 10*cur + v;
                }
                res += sign*cur;
            }
            else if(c == '+')   sign  = 1;
            else if(c == '-')   sign = -1;
            else if(c == '('){
                stk.push(res);
                res = 0;
                stk.push(sign);//括号前面的符号位
                sign= 1;
            }
            else if(c == ')'){
                int a = stk.top(); stk.pop();//符号
                int b = stk.top(); stk.pop();
                res = a*res + b;
            }
        }
        return res;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/848223
推荐阅读
相关标签
  

闽ICP备14008679号