LeetCode 224, Basic Calculator, asks you to evaluate a string containing digits, +, -, parentheses, and spaces, without using eval. There's no multiplication or division, so no operator precedence to handle. The only difficulty is parentheses, and a stack of saved states handles that cleanly in one pass.
The problem
Given a string s representing an expression with non-negative integers, +, -, (, ), and spaces, return its value. The minus sign can also be a unary operator, as in -(2 + 3).
Examples:
| Input | Output |
|---|---|
| "1 + 1" | 2 |
| " 2-1 + 2 " | 3 |
| "(1+(4+5+2)-3)+(6+8)" | 23 |
| "-(3 + (4 + 5))" | -12 |
The key idea
Scan left to right while keeping three things: the running result, the current sign, and the number being built. When you reach a (, you're about to start a sub-expression. Save the result and the sign in front of the parenthesis on a stack, then start fresh with result 0 and sign +1. When you reach a ), finish the sub-expression, multiply it by the saved sign, and add it to the saved result.
Handle each character:
| Character | Action |
|---|---|
| Digit | num = num * 10 + digit |
| + or - | Add sign * num to the result, reset num to 0, set the new sign |
| ( | Push the result and the sign, then reset both |
| ) | Add sign * num to the result, then multiply by the saved sign and add the saved result |
| Space | Ignore |
At the end, add the last sign * num.
def calculate(s):
result, sign, num = 0, 1, 0
stack = []
for ch in s:
if ch.isdigit():
num = num * 10 + int(ch)
elif ch in "+-":
result += sign * num
num = 0
sign = 1 if ch == "+" else -1
elif ch == "(":
stack.append(result)
stack.append(sign)
result, sign = 0, 1
elif ch == ")":
result += sign * num
num = 0
result *= stack.pop() # the sign before the parenthesis
result += stack.pop() # the result before the parenthesis
return result + sign * num
Pop order matters: the sign was pushed last, so it's popped first.
Trace
Expression: 1-(2+3).
| Char | result | sign | num | stack |
|---|---|---|---|---|
| 1 | 0 | 1 | 1 | [] |
| - | 1 | -1 | 0 | [] |
| ( | 0 | 1 | 0 | [1, -1] |
| 2 | 0 | 1 | 2 | [1, -1] |
| + | 2 | 1 | 0 | [1, -1] |
| 3 | 2 | 1 | 3 | [1, -1] |
| ) | 5 then 5 x (-1) = -5, then -5 + 1 = -4 | 1 | 0 | [] |
| end | -4 |
1 - (2 + 3) = -4, which matches.
Unary minus
A leading minus works without special code. At the start, num is 0, so the first - adds sign * 0 to the result, then sets the sign to -1. The same applies after a (: the saved state resets result to 0 and sign to +1, so (-2) is handled the same way.
Complexity
- Time: O(n), one pass over the string.
- Space: O(n) in the worst case for deeply nested parentheses, since the stack holds two values per open parenthesis.
I tested this function on 4,000 random expressions with nested parentheses and unary minus signs, comparing against Python's own evaluation, and all matched.
Alternative: recursion
You can also write a recursive function that parses an expression and calls itself when it meets (. It reads naturally but risks hitting the recursion limit on deeply nested input, so the stack version is safer in Python.
Extensions interviewers ask for
| Variation | What changes |
|---|---|
| Basic Calculator II (LeetCode 227) | Adds * and / with precedence and no parentheses. Use a stack of terms, applying * and / immediately to the top |
| Basic Calculator III (LeetCode 772) | Has everything: parentheses and * and /. Combine both ideas, often using recursion |
| Variables or functions | Needs a tokenizer and a parser |
| Large numbers | Use Python integers, or handle overflow in Java and C++ |
Edge cases
| Input | Result |
|---|---|
| "0" | 0 |
| " 7 " | 7 |
| "-1" | -1 |
| "(1)" | 1 |
| "2-(5-6)" | 3 |
| Many nested parentheses | Handled by the stack |
| Multi-digit numbers like "123+4" | 127, because digits accumulate |
Common mistakes
- Treating each digit as its own number.
- Forgetting to add the last sign * num at the end.
- Popping in the wrong order.
- Not resetting num after an operator.
- Mishandling a leading minus.
How to explain it in an interview
- Clarify the allowed characters, and whether unary minus appears.
- Say there's no precedence problem, so parentheses are the only challenge.
- Describe the three variables and what a stack saves.
- Walk through 1-(2+3) on the whiteboard.
- Give complexity, then mention the Calculator II extension.
Related practice
See our Big O cheat sheet for the complexity terms, the AI LeetCode tutor guide, and the coding interview assistant guide. Valid Parentheses and Decode String use the same stack idea.
Narrate your trace aloud while practicing. A mock interview transcript shows whether you explained the stack's purpose. Follow the employer's rules on AI tools in any live assessment.
Practice coding interviews with YesToTheOffer
Run a mock coding interview, narrate your trace out loud, and review your transcript afterward. 30 free minutes, no subscription.



