• LeetCode Basic Calculator


    Implement a basic calculator to evaluate a simple expression string.

    The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces .

    You may assume that the given expression is always valid.

    Some examples:

    "1 + 1" = 2
    " 2-1 + 2 " = 3
    "(1+(4+5+2)-3)+(6+8)" = 23
    

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

    先用最通用的(转换为后缀表达式,然后对后缀表达式求值):

    class Solution {
    public:
        int calculate(string s) {
            vector<long> postfix = to_postfix(s);
            int len = postfix.size();
            if (len == 0) {
                return 0;
            }
            vector<long> tmp;
            long a, b;
            for (int i=0; i<len; i++) {
                long ch = postfix[i];
                switch(ch) {
                    case '+':
                        a = tmp.back();
                        tmp.pop_back();
                        tmp.back() = tmp.back() + a;
                        break;
                    case '-':
                        a = tmp.back();
                        tmp.pop_back();
                        tmp.back() = tmp.back() - a;
                        break;
                    default:
                        tmp.push_back(-ch);
                }
            }
            return tmp[0];
        }
        
        vector<long> to_postfix(const string& s) {
            int len = s.size();
            // operators
            vector<char> operato;
            // generated postfix experssion of this infix experssion
            vector<long> postfix;
            
            int val = 0;
            bool innum = false;
            
            for (int i=0; i<len; i++) {
                char ch = s[i];
                switch (ch) {
                    case ' ':
                        // skip space
                        continue;
                    case '-':
                    case '+':
                        while (!operato.empty() && operato.back() != '(') {
                            postfix.push_back(operato.back());
                            operato.pop_back();
                        }
                        operato.push_back(ch);
                        break;
                    case '(':
                        // just push to operato
                        operato.push_back(ch);
                        break;
                    case ')':
                        // move any operato between this ')' and it's paired '('
                        while (!operato.empty() && operato.back() != '(') {
                            postfix.push_back(operato.back());
                            operato.pop_back();
                        }
                        // destroy '(' placeholder
                        operato.pop_back();
                        break;
                    default:
                        if (innum) {
                            val = val * 10 + ch - '0';
                        } else {
                            val = ch - '0';
                            innum = true;
                        }
                        // look ahead
                        if (i+1 == len || s[i+1] > '9' || s[i+1] < '0') {
                            postfix.push_back(-val);
                            innum = false;
                        }
                }
            }
            
            while (!operato.empty()) {
                postfix.push_back(operato.back());
                operato.pop_back();
            }
            return postfix;
        }
    };

     下面这个用递归的方式处理每个括号中的表达式,但是MLE

    class Solution {
    public:
        int calculate(string s) {
            int len = s.size();
            int val = 0;
            char lastop = '+';
            for (int i=0; i<len; i++) {
                char ch = s[i];
                switch(ch) {
                    case ' ':
                        break;
                    case '(':{
                        int cnt = 1;
                        int idx = ++i;
                        while (cnt != 0) {
                            if (s[i] == '(') {
                                cnt++;
                            } else if (s[i] == ')') {
                                cnt--;
                            }
                            i++;
                        }
                        i--;
                        int t = calculate(s.substr(idx, i - idx));
                        val = lastop == '-' ? (val - t) : (val + t);
                        
                    }; break;
                    case ')':{
                        
                    };break;
                    case '+':
                    case '-':
                        lastop = ch;
                        break;
                    default:
                        // numbers
                        int num = 0;
                        while ((i) < len && s[i] <= '9' && s[i] >= '0') {
                            num = num * 10 + ch - '0';
                            i++;
                        }
                        i--;
                        val = lastop == '-' ? (val - num) : (val + num);
                }
            }
            
            return val;
        }
    };

     好了,来个简洁的,因为只涉及到加减法,其实我们可以把括号全部化简掉,在这个过程中应用负负得正的这些规律,正确得到多层括号内数值最终的符号:

    class Solution {
    public:
        int calculate(string s) {
            vector<int> sign;
            sign.push_back(1);
            
            char last_op = '+';
            int len = s.size();
            
            long val = 0;
            
            for (int i=0; i<len; i++) {
                char ch = s[i];
                switch(ch) {
                    case ' ':
                        break;
                    case '+':
                    case '-':
                        last_op = ch;
                        break;
                    case '(':
                        // enter a new sign context
                        sign.push_back(sign.back() * (last_op == '-' ? -1 : 1));
                        last_op = '+';
                        break;
                    case ')':
                        // exit a sign context
                        sign.pop_back();
                        break;
                    default:
                        // numbers;
                        int num = 0;
                        while (i < len && s[i] >= '0' && s[i] <= '9') {
                            num = num * 10 + s[i] - '0';
                            i++;
                        }
                        i--;
                        val += (last_op == '-'?-1:1) * sign.back() * num;
                }
            }
            return val;
        }
    };
  • 相关阅读:
    mac os x 之通过远程主机在nginx上部署web静态页面
    基于jQuery UI的调色板插件推荐colorpicker
    Mac 访问隐藏文件方法! 网上方法在我电脑上都不可用!
    JavaScript设计模式学习之单例模式
    由一篇博文做出的代码,不用Math.round()如何实现其功能
    mac os x之解决npm安装包失败,或者nodejs工程缺少依赖
    用nginx的反向代理机制解决前端跨域问题
    mac之os x系统下搭建nodejs+express4.x+mongodb+gruntjs整套前端工程
    sourcetree window10 闪退
    滚动条自定义样式
  • 原文地址:https://www.cnblogs.com/lailailai/p/4565007.html
Copyright © 2020-2023  润新知