- Interview Questions
- /
- Problems
- /
- Basic Calculator
Basic Calculator
Evaluate a string expression with +, -, parentheses and unary minus, without eval. A single pass with a stack that saves your place at each open parenthesis. Solve it below in Python or JavaScript, then read the walkthrough.
Problem
You're given a string s holding a valid arithmetic expression. Evaluate it and return the integer result. You may not use any built-in function that evaluates strings as code (such as eval).
The expression contains only:
- non-negative integers (possibly several digits long),
- the binary operators
+and-, - parentheses
(and), - spaces, which can appear anywhere and should be ignored.
A - may also be unary, negating what follows it, but only at the very start of the expression or right after an (. A + is never unary, and two operators never appear next to each other.
Example 1
- Input
- s = "7 - (3 + 2)"
- Output
- 2
Example 2
- Input
- s = "-(4 - 10) + 1"
- Output
- 7
The leading minus negates the group: -(-6) + 1 = 7.
Example 3
- Input
- s = "12+ (5-(8 -2))"
- Output
- 11
The inner group is 6, so the outer one is 5 - 6 = -1, and 12 + (-1) = 11.
Constraints
- 1 ≤ s.length ≤ 3 × 10⁵
- s contains digits, "+", "-", "(", ")" and spaces.
- s is a valid expression.
- Every intermediate value and the result fit in a signed 32-bit integer.
Practice
Runs 14 tests in your browser. Python loads on the first run (about 6 MB, then cached). Press ⌘/Ctrl + Enter to run.
Get asked Basic Calculator in a real interview?
Interview Solver gives you a working solution live, during your actual coding interview. Invisible to screensharing.
How to solve Basic Calculator
Pattern: Running sum with a stack of saved contexts
With only + and -, there's no precedence to worry about. Without parentheses you could just keep a running result and a sign (+1 or -1) for the next number: every time a number ends, add sign * number to result.
Parentheses are the only complication, and they nest like a stack. When you hit (, the work you've done so far is on hold: push the current result and the sign in front of the parenthesis, then start a fresh result of 0 for the inside. When you hit ), the inside is finished; pop the saved pair and fold it back in as saved_result + saved_sign * inside.
Unary minus falls out for free. At the start of the expression or right after (, result is 0, so a - just adds 0 and sets sign = -1 for what follows.
Approach 1: Recursive descent
Write a parser where parse_expression reads terms separated by +/-, and a term is either a number or ( expression ). Clear and easy to extend to * and /, but recursion depth equals the nesting depth, which can overflow the call stack on deeply nested input.
Time O(n) · Space O(n)
Approach 2: Convert to postfix, then evaluate
Run the shunting-yard algorithm to produce reverse Polish notation, then evaluate it with a value stack. Unary minus needs a special token (for example rewrite it as 0 -). Works, but it is two passes and more code than the problem needs.
Time O(n) · Space O(n)
Approach 3: Single pass with a sign stack
Track result, number (digits being read) and sign. For each character:
- Digit:
number = number * 10 + digit. +or-: addsign * numbertoresult, resetnumber, setsignto +1 or -1.(: push(result, sign), then resetresult = 0,sign = 1.): addsign * numbertoresult, resetnumber, pop(saved, saved_sign)and setresult = saved + saved_sign * result.- Spaces: skip.
At the end return result + sign * number to include the last number.
Time O(n) · Space O(n)
| Approach | Time | Space |
|---|---|---|
| Recursive descent | O(n) | O(n) |
| Convert to postfix, then evaluate | O(n) | O(n) |
| Single pass with a sign stack | O(n) | O(n) |
Solution code
Try the practice editor first. Both solutions pass every test above.
Basic Calculator solution in Python
def calculate(s: str) -> int:
result = 0
number = 0
sign = 1
stack = [] # (result before "(", sign in front of "(")
for ch in s:
if ch.isdigit():
number = number * 10 + int(ch)
elif ch == "+" or ch == "-":
result += sign * number
number = 0
sign = 1 if ch == "+" else -1
elif ch == "(":
stack.append((result, sign))
result, sign = 0, 1
elif ch == ")":
result += sign * number
number = 0
saved, saved_sign = stack.pop()
result = saved + saved_sign * result
return result + sign * numberBasic Calculator solution in JavaScript
function calculate(s) {
let result = 0;
let number = 0;
let sign = 1;
const stack = []; // [result before "(", sign in front of "("]
for (const ch of s) {
if (ch >= '0' && ch <= '9') {
number = number * 10 + (ch.charCodeAt(0) - 48);
} else if (ch === '+' || ch === '-') {
result += sign * number;
number = 0;
sign = ch === '+' ? 1 : -1;
} else if (ch === '(') {
stack.push([result, sign]);
result = 0;
sign = 1;
} else if (ch === ')') {
result += sign * number;
number = 0;
const [saved, savedSign] = stack.pop();
result = saved + savedSign * result;
}
}
return result + sign * number;
}Common mistakes
- Reading only one digit per number. "42" must parse as forty-two, so accumulate digits until a non-digit appears.
- Forgetting to add the final number after the loop. "7 - 3" ends on a digit, so nothing inside the loop flushes it.
- Not flushing the pending number at `)` before popping, which drops the last number inside the group.
- Applying the sign in front of `(` to only the first number inside, instead of to the whole group's value.
- Using recursion on input with hundreds of nested parentheses and hitting the recursion limit in Python.
What interviewers look for
Clarify the grammar first: which operators, whether unary minus exists and where, and whether spaces can appear inside numbers (they can't here). Interviewers like hearing you pin that down.
Then explain the state you carry: "result so far, the number I'm reading, and the sign for it. A parenthesis pushes that state and starts fresh." Trace an example with a negated group, like -(4 - 10), since that's the case most solutions get wrong.
Follow-up questions
How would you add * and /?
Without parentheses, keep a stack of terms: push +n or -n for additive operators, and for * or / pop the top term, combine it with the new number, and push the result. Sum the stack at the end. With parentheses too, a recursive descent parser with separate expression and term levels is the cleanest.
Can you do it with O(1) extra space?
Not in general, since you need to remember the sign context for every open parenthesis. You can shrink the stack to only signs (push the effective sign for each group and multiply it into every number), but it still grows with nesting depth.
How would you report invalid input?
Track the previous token type to reject two operators in a row or an operator before `)`, check the stack is non-empty on `)`, and check it is empty at the end. Report the position of the first bad character.
Companies that ask Basic Calculator
Basic Calculator is tagged by 118 companies in our interview dataset. The score shows how often it comes up at each company.
- Ch Robinson100%
- Workspan100%
- Intuitive100%
- Adesso100%
- Dandy100%
- Rokt100%
- Udemy98%
- Motional96%
- Cytokinetics94%
- Lime94%
- Traveloka92%
- Supermicro89%
- Mts89%
- Doximity87%
- Squarepoint Capital85.1%
- Raytheon84%
- Front84%
- Genpact84%
- Albertsons83%
- Skillz83%
- Procore Technologies82%
- Disco Corporation81%
- Relativity78%
- Ripple77.9%
and 94 more.
Practice next
Get live help in the real interview
Working solutions in real time during your actual interview. Invisible to screensharing.
Start Free TrialNo credit card required