基本计算器类问题(栈)

150. 逆波兰表达式求值

根据 逆波兰表示法,求表达式的值。

有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

 

说明:

整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
 

示例 1:

输入: ["2", "1", "+", "3", "*"]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:

输入: ["4", "13", "5", "/", "+"]
输出: 6
解释: 该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:

输入: ["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

 

这题算是较为简单的题了,不用考虑顺序问题,用一个stack就可以解决。

每次读到符号时,从栈中弹出两个数据进行相应的运算,之后再存在栈中即可。

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> sta;
        int n = tokens.size();
        int fir,sec;
        for(int i = 0; i < n; i++){
            if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/"){
                sec = sta.top();
                sta.pop();
                fir = sta.top();
                sta.pop();
                if(tokens[i] == "+")  sta.push(fir + sec);
                else if(tokens[i] == "-") sta.push(fir - sec);
                else if(tokens[i] == "*") sta.push(fir * sec);
                else   sta.push(fir / sec);
            }
            else{
                int length = tokens[i].size();
                string temp = tokens[i];
                int j = 0,sign = 1,sum = 0;
                while(j < length){
                    if(temp[j] == '-' || temp[j] == '+'){
                        if(temp[j] == '-')  sign = -1;
                        else sign = 1;
                    }
                    else{
                        sum = sum * 10 + temp[j] - 48;
                    }
                    j++;
                }
                sum *= sign;
                sta.push(sum);
            }
        }
        return sta.top();
    }
};

224. 基本计算器

实现一个基本的计算器来计算一个简单的字符串表达式 s 的值。

 

示例 1:

输入:s = "1 + 1"
输出:2
示例 2:

输入:s = " 2-1 + 2 "
输出:3
示例 3:

输入:s = "(1+(4+5+2)-3)+(6+8)"
输出:23

因为没有乘法的除法,因此,如果展开表达式中所有的括号,则得到的新表达式中,数字本身不会发生变化,只是每个数字前面的符号会发生变化。

因此,我们考虑使用一个取值为 {-1,+1} 的整数 sign代表「当前」的符号。根据括号表达式的性质,它的取值:

与字符串中当前位置的运算符有关;
如果当前位置处于一系列括号之内,则也与这些括号前面的运算符有关:每当遇到一个以 - 号开头的括号,则意味着此后的符号都要被「翻转」

class Solution {
public:
    int calculate(string s) {
        int n = s.size();
        int sign = 1;
        stack<int> sta;
        sta.push(1);
        int sum = 0,i = 0;
        while(i < n){
            switch(s[i]){
                // 遇到括号把前面的符号存起来,如果是-1的话括号里面的数都乘-1
                case ' ' :
                    i++;
                    break;
                case '+' :
                    sign = sta.top();
                    i++;
                    break;
                case '-' :
                    sign = -sta.top();
                    i++;
                    break;
                case '(' :
                    sta.push(sign);
                    i++;
                    break;
                case ')' :
                    sta.pop();
                    i++;
                    break;
                default :
                    long temp = 0;
                    while(i < n && s[i] >= '0' & s[i] <= '9'){
                        temp = temp * 10 + s[i] - 48;
                        i++;
                    }
                    sum += temp * sign;
                    cout << sum;
                    break;
            }
        }
        return sum;
    }
};

 

227. 基本计算器 II

实现一个基本的计算器来计算一个简单的字符串表达式的值。

字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格  。 整数除法仅保留整数部分。

示例 1:

输入: "3+2*2"
输出: 7
示例 2:

输入: " 3/2 "
输出: 1
示例 3:

输入: " 3+5 / 2 "
输出: 5

这道题多了* 和 / ,所以需要考虑优先级的问题,我们可以在遇到一个数字结束后(有可能是遇到符号,或者空格,或者是字符串的末尾),把之前存取在sign的符号取出来

如果是'+': 就把当前数字存到栈里

如果是’-‘: 就把当前数字取反存到栈里

如果是’*’: 把当前数字和之前存到栈里的数字相乘后存到栈里

如果是‘/’: 把当前数字和之前存到栈里的数字相除后存到栈里

 

class Solution {
public:
    int calculate(string s) {
        int n = s.size();
        char sign = '+';
        stack<int> num;
        int cur = 0;
        int sum = 0;
        int temp;
        for(int i = 0; i < n; i++){
            if(s[i] >= '0'){
               //cur 是当前正在遍历的数字
                cur = cur * 10 - 48 + s[i];
            }
            //当前的数字过了,需要处理一下之前的sign和cur
            if(s[i] < '0' && s[i] != ' ' || i == n - 1){
                //上一个保存的符号
                switch(sign){
                    case '+' :
                        num.push(cur);  break;
                    case '-' :
                        num.push(-cur); break;
                    case '*' :
                        temp = num.top();
                        num.pop();
                        num.push(temp * cur);
                        break;
                    case '/' :
                        temp = num.top();
                        num.pop();
                        num.push(temp / cur);
                        break;
                }
                // 保存这次的符号
                sign = s[i];
                cur = 0;
            }
        }
        while(!num.empty()){
            sum += num.top();
            num.pop();
        }
        return sum;
    }
};    

 

posted @ 2021-03-10 14:53  小码农2  阅读(123)  评论(0)    收藏  举报