Skip to content

0224. Basic Calculator

Given a string s representing a valid expression, implement a basic calculator to evaluate it, and return the result of the evaluation.

Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval().

Example 1:

Input: s = "1 + 1"
Output: 2

Example 2:

Input: s = " 2-1 + 2 "
Output: 3

Example 3:

Input: s = "(1+(4+5+2)-3)+(6+8)"
Output: 23

Constraints:

  • 1 <= s.length <= 3 * 105
  • s consists of digits, '+', '-', '(', ')', and ' '.
  • s represents a valid expression.
  • '+' is not used as a unary operation (i.e., "+1" and "+(2 + 3)" is invalid).
  • '-' could be used as a unary operation (i.e., "-1" and "-(2 + 3)" is valid).
  • There will be no two consecutive operators in the input.
  • Every number and running calculation will fit in a signed 32-bit integer.

Analysis

The hard part of this problem is to consider the parentheses case since it will alter the calculation sequence. To solve this issue, we can use a stack to store the number value into a stack, so that we can reuse it later.

For example: str = "1+(2-3)"

step 1:
stk:
i: str[0] -> 1

step 2:
stk:
i: str[1] -> +

step 3:
stk: 1, +
i: str[2] -> (

step 4:
stk: #note that the stack is popped twice because for any binary operation it takes two arguments and one operator
i: str[3] -> 2
...
  • Time: O(n) for stack it only takes O(2) so not a O(n^2) operation in total
  • Space: O(n) for a lot of nested parentheses case

Code

class Solution {
public:
    int calculate(string s) {
        int res = 0, sign = 1, n = s.size();
        stack<int> st;
        for (int i = 0; i < n; ++i) {
            char c = s[i];
            if (c >= '0') {// it's number
                int num = 0;
                while (i < n && s[i] >= '0') {
                    num = 10 * num + (s[i++] - '0');
                }
                // now we should add the whole number to the resultant value
                res += sign * num;
                // update the offset, since it's already pointing to the next 
                // char we are looking, and the for loop will update the index again
                --i;
            } else if (c == '+') {
                sign = 1;
            } else if (c == '-') {
                sign = -1;
            } else if (c == '(') {
                st.push(res);
                st.push(sign);
                res = 0;
                sign = 1;
            } else if (c == ')') {
                res *= st.top();
                st.pop();
                res += st.top();
                st.pop();
            }
        }
        return res;
    }
};

Last update: April 1, 2022