Difficulty: Hard
Topics: Stack, Math, String, Recursion
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().
Input: s = "1 + 1"
Output: 2
Input: s = " 2-1 + 2 "
Output: 3
Input: s = "(1+(4+5+2)-3)+(6+8)"
Output: 23
$1 \le \text{s.length} \le 3 \times 10^5$ -
sconsists of digits,+,-,(,), and' '. -
srepresents a valid expression. -
+is not used as a unary operation. -
-could be used as a unary operation. - There will be no two consecutive operators in the input.
- Every number and running calculation will fit in a signed 32-bit integer.
Because the operators are strictly additive (+ and -) with parentheses:
- We can maintain a running accumulation
currentResultand a sign trackersign($+1$ or$-1$ ). - When parsing a number
$V$ , we instantly update:$$\text{currentResult} += \text{sign} \times V$$
-
Entering Parenthesis
(:- Push
currentResultonto the stack (the outer accumulated value). - Push
signonto the stack (the overall sign modifying the upcoming parenthesized block). - Reset
currentResult = 0andsign = 1to start accumulating the inner sub-expression.
- Push
-
Exiting Parenthesis
):- Pop the block sign
prevSign. - Pop the outer result
prevResult. - Merge:
$$\text{currentResult} = \text{prevResult} + \text{prevSign} \times \text{currentResult}$$
- Pop the block sign
Expressions like -(2 + 3) or - (3 - (- (4 + 5))) naturally work:
- Encountering
-setssign = -1. - Immediately encountering
(pushesprevSign = -1and resets. - When
)closes, the entire evaluated inner block is multiplied by$-1$ .
-
Time Complexity:
$\mathcal{O}(N)$ where$N = |s| \le 3 \times 10^5$ (single pass with$\mathcal{O}(1)$ per character). -
Space Complexity:
$\mathcal{O}(N)$ auxiliary memory for the evaluation stack proportional to the nesting depth.
- Leading Unary Minus:
"-2 + 1" \implies -1and"-(2 + 3)" \implies -5. - Arbitrary Whitespace: Skipped smoothly without interrupting token accumulation.
- Deeply Nested Expressions: Handled with linear stack frames.