[LeetCode]104. Basic Calculator II基本计算器

Implement a basic calculator to evaluate a simple expression string.

The expression string contains only non-negative integers, +-*/ operators and empty spaces . The integer division should truncate toward zero.

You may assume that the given expression is always valid.

Some examples:

"3+2*2" = 7
" 3/2 " = 1
" 3+5 / 2 " = 5

Note: Do not use the eval built-in library function.

本题与基本计算器I不同的一点是表达式不包含括号,取而代之的是包含有乘除运算。

解法1:先遍历一遍表达式去除无效的空格。然后从头至尾遍历表达式,遇到数字和加减号分别进操作数或操作符栈,遇到乘除号则在操作数栈中取出左操作数,同时从表达式中读出右操作数,计算好结果后入操作数栈。一遍完成后将乘除运算计算完成。根据加减运算的从左至右规律,先将操作数和操作符栈中的元素全部搬运到新的操作数和操作符栈,然后不断从新的操作符栈取操作符,从新的操作数栈取两个操作数,进行加减运算,直至没有操作符,操作数栈顶即为结果。

class Solution {
public:
    int calculate(string s) {
        stack<char> opc;
        stack<int> opn;
        int k = 0;
        for (int i = 0; i < s.size(); ++i) {
            if (!isspace(s[i])) s[k++] = s[i];
        }
        s.resize(k);
        for (int i = 0; i < k; ++i) {
            if (isdigit(s[i])) {
                int d = s[i] - '0';
                while (i < k && isdigit(s[++i]))
                    d = d * 10 + s[i] - '0';
                --i;
                opn.push(d);
            }
            else if (s[i] == '+' || s[i] == '-')
                opc.push(s[i]);
            else if (s[i] == '*' || s[i] == '/') {
                char dom = s[i];
                int num1 = opn.top();
                opn.pop();
                int num2 = (int)(s[++i] - '0');
                while (i < k && isdigit(s[++i]))
                    num2 = num2 * 10 + s[i] - '0';
                --i;
                if (dom == '*') opn.push(num1 * num2);
                else opn.push(num1 / num2);
            }
        }
        stack<char> c;
        stack<int> n;
        while (!opc.empty()) {
            c.push(opc.top());
            opc.pop();
        }
        while (!opn.empty()) {
            n.push(opn.top());
            opn.pop();
        }
        while (!c.empty()) {
            int num1 = n.top();
            n.pop();
            int num2 = n.top();
            n.pop();
            char aoa = c.top();
            c.pop();
            if (aoa == '+') n.push(num1 + num2);
            else n.push(num1 - num2);
        }
        return n.top();
    }
};

解法2:解法1的一个繁琐之处在于为了从左至右计算加减运算需将两个栈倒过来,可以想办法将这个过程省去。每次遇到第二个操作符,只要不是乘除号,则可以将前面一部分表达式按从左至右顺序计算好。

class Solution {
public:
    int calculate(string s) {
        stack<char> opc;
        stack<int> opn;
        int k = 0;
        for (int i = 0; i < s.size(); ++i) {
            if (!isspace(s[i])) s[k++] = s[i];
        }
        s.resize(k);
        for (int i = 0; i < k; ++i) {
            if (isdigit(s[i])) {
                int d = s[i] - '0';
                while (isdigit(s[++i]))
                    d = d * 10 + s[i] - '0';
                --i;
                opn.push(d);
            }
            else if (s[i] == '+' || s[i] == '-') {
                if (!opc.empty()) {
                    char dom = opc.top();
                    opc.pop();
                    int num2 = opn.top();
                    opn.pop();
                    int num1 = opn.top();
                    opn.pop();
                    if (dom == '+') opn.push(num1 + num2);
                    else opn.push(num1 - num2);
                }
                opc.push(s[i]);
            }
            else if (s[i] == '*' || s[i] == '/') {
                char dom = s[i];
                int num1 = opn.top();
                opn.pop();
                int num2 = (int)(s[++i] - '0');
                while (isdigit(s[++i]))
                    num2 = num2 * 10 + s[i] - '0';
                --i;
                if (dom == '*') opn.push(num1 * num2);
                else opn.push(num1 / num2);
            }
        }
        if (!opc.empty()) {
            char dom = opc.top();
            opc.pop();
            int num2 = opn.top();
            opn.pop();
            int num1 = opn.top();
            opn.pop();
            if (dom == '+') opn.push(num1 + num2);
            else opn.push(num1 - num2);
        }
        return opn.top();
    }
};

解法3:将中缀表达式转换为前缀或者后缀表达式再进行计算。见基本计算器I

原文地址:https://www.cnblogs.com/aprilcheny/p/5032924.html