美文网首页
224. Basic Calculator (Hard)

224. Basic Calculator (Hard)

作者: Ysgc | 来源:发表于2020-11-20 01:02 被阅读0次

    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 .

    Example 1:

    Input: "1 + 1"
    Output: 2
    Example 2:

    Input: " 2-1 + 2 "
    Output: 3
    Example 3:

    Input: "(1+(4+5+2)-3)+(6+8)"
    Output: 23
    Note:
    You may assume that the given expression is always valid.
    Do not use the eval built-in library function.


    我的答案:用stack

    class Solution {
    public:
        int calculate(string s) {
            s = "+(" + s + ")";
            // cout << s << endl;
            stack<int> sign({1});
            stack<int> value({0});
            
            unordered_map<char,int> type_map{
                {'+', 1}, {'-', -1}, {'(', 2}, {')', -2}
            };
            for (int i=0; i<10; ++i) {
                type_map[i] = 0;
            }
            
            int left = 0;
            int right = 0;
            int last_type = 3;
            for (int i=0; i<s.size(); ++i) {
                char c = s[i];
                if (c == ' ') {
                    right = (last_type == 0)? i:-1;
                    // cout << i << ": " << c << " is space, right is " << right << ", left is " << left << endl;
                    continue;
                }
                
                int curr_type = type_map[c];
                // cout << i << ": " << c << ": " << curr_type << endl;
                if (last_type == 0 and curr_type != 0) {
                    right = (right>left)? right:i;
                    // cout << "[" << left << ", " << right << ")" << endl;
                    // cout << s.substr(left, right-left) << endl;
                    value.top() += stoi(s.substr(left, right-left))*sign.top();
                    sign.pop();
                }
                if (last_type!= 0 and curr_type == 0) {
                    left = i;
                    if (abs(last_type) != 1) {
                        sign.push(1);
                    }
                }
                if (abs(curr_type) == 1) {
                    sign.push(curr_type);
                }
                if (curr_type == 2) {
                    if (abs(last_type) != 1) {
                        sign.push(1);
                    }
                    value.push(0);
                }
                if (curr_type == -2) {
                    int temp = value.top();
                    value.pop();
                    value.top() += temp*sign.top();
                    sign.pop();
                }
                    
                last_type = curr_type;
            }
            
            return value.top();
        }
    };
    

    Runtime: 32 ms, faster than 35.62% of C++ online submissions for Basic Calculator.
    Memory Usage: 9.9 MB, less than 35.88% of C++ online submissions for Basic Calculator.

    一遍过,开心!但是速度有点慢

    主要是用stack存两个信息,一个是sign,一个是value
    每个数结束之后要乘以sign,加到value的top上
    每个括号结束的时候,要乘以sign,加到value的second top上,当前top pop出去

    第一行处理了一下s成为s = "+(" + s + ")";,不然结尾


    看了下答案:

    // Author: Huahua
    class Solution {
    public:
      int calculate(string s) {    
        function<int(int&)> eval = [&](int& pos) {
          int ret = 0;
          int sign = 1;
          int val = 0;
          while (pos < s.size()) {
            const char ch = s[pos];
            if (isdigit(ch)) {
              val = val * 10 + (s[pos++] - '0');
            } else if (ch == '+' || ch == '-') {
              ret += sign * val;
              val = 0;
              sign = ch == '+' ? 1 : -1;
              ++pos;
            } else if (ch == '(') {
              val = eval(++pos);
            } else if (ch == ')') {          
              ++pos;
              break;
            } else {
              ++pos;
            }
          }
          return ret += sign * val;
        };
        int pos = 0;
        return eval(pos);
      }
    };
    

    8ms

    我觉得我的代码比较慢的原因有2个,一个是其实是n^2,因为得回去看left right substring。小trick是用isdigit判断是否是0-9。

    默写了一次:

    class Solution {
    public:
        int calculate(string s) {
            int pos = 0;
            return eval(pos, s);
        }
        int eval(int& pos, string& s) {
            int ret = 0;
            int val = 0;
            int sign = 1;
            while (pos < s.size()) {
                char c = s[pos];
                // cout << pos << " : " << c << endl;
                // cout << "sign = " << sign << ", val = " << val << ", ret = " << ret << endl;
                if (isdigit(c)) {
                    val = val*10 + (c-'0');
                    ++pos;
                }
                else if (c == '+' or c == '-') {
                    ret += sign*val;
                    val = 0;
                    sign = (c == '+')? 1:-1;
                    ++pos;
                }
                else if (c == '(') {
                    ret += sign*eval(++pos, s);
                }
                else if (c == ')') {
                    ++pos;
                    return ret += val*sign;
                }
                else {
                    ++pos;
                }
            }
            ret += val*sign;
            return ret;
        }
    };
    

    用recursion替代了写stack,sign也只需要当下的,pos是reference,所以是全局的index。处理结尾的方式是,在return之前再多做一次ret += val*sign;

    相关文章

      网友评论

          本文标题:224. Basic Calculator (Hard)

          本文链接:https://www.haomeiwen.com/subject/lmgkiktx.html