Home
DSA Patterns
Stack
Basic Calculator
Basic Calculator
Evaluate an expression of +, - and nested brackets without eval, using a running sum and a stack that saves the sum and sign at every open bracket.
Problem Understanding
Basic Calculator (LeetCode 224): evaluate a valid expression string made of non-negative integers, +, -, (, ) and spaces, without using a built-in evaluator. - can also be unary, as in -1 or -(2 + 3), but + is never unary.
Examples: "1 + 1" → 2; " 2-1 + 2 " → 3; "(1+(4+5+2)-3)+(6+8)" → 23.
The Intuition: Save the Outside, Solve the Inside
Without brackets this is just a running sum: read a number, add or subtract it, move on. A bracket is a smaller sum that has to be finished first.
- Read left to right, building each number digit by digit.
- At
(, park the outer sum and the sign in front of the bracket on a stack, and start a new sum at 0. - At
), the inner sum is done. Pop the sign and the outer sum and combine: outer + sign × inner.
The stack only ever holds one entry per open bracket. Basic Calculator II uses a stack for * and / instead, and Valid Parentheses is the same open-close matching without the arithmetic.
Interactive Walkthrough
( SAVES ) FOLDS
START
s
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
stack: sum, sign
empty
result
0
sign
+
num
0
result = 0, sign = +1, num = 0, and an empty stack
Next
'(': save the sum so far (0) and the sign in front of the bracket (+), then start a fresh sum
s
The stack beside the expression shows one saved "sum, sign" pair per open bracket. Try Minus bracket: the minus in front of ( is saved with it, so the bracket's total folds back as a negative.
Dry Run Table
Input: s = "(1+(4+5+2)-3)+(6+8)".
| Character | What happens | result | stack (sum, sign) |
|---|---|---|---|
( at 0 |
save 0, + and start fresh | 0 | [0, +] |
1+ |
result = 1 | 1 | [0, +] |
( at 3 |
save 1, + and start fresh | 0 | [0, +] [1, +] |
4+5+2 |
4, 9, then num = 2 | 9 | [0, +] [1, +] |
) at 9 |
the bracket is 9 + 2 = 11; fold back: 1 + 11 | 12 | [0, +] |
-3 |
sign -, num = 3 | 12 | [0, +] |
) at 12 |
the bracket is 12 - 3 = 9; fold back: 0 + 9 | 9 | [] |
+( |
result 9, save 9, + and start fresh | 0 | [9, +] |
6+8) |
the bracket is 14; fold back: 9 + 14 | 23 | [] |
Answer: 23.
The Solution Template
One pass with result, sign, num and a stack of saved (sum, sign) pairs. Spaces fall through every branch and are skipped.
Basic Calculator Code
1var calculate = function(s) {2 let result = 0, sign = 1, num = 0;3 const stack = [];4 for (const c of s) {5 if (c >= '0' && c <= '9') {6 num = num * 10 + (c.charCodeAt(0) - 48);7 } else if (c === '+' || c === '-') {8 result += sign * num;9 sign = c === '+' ? 1 : -1;10 num = 0;11 } else if (c === '(') {12 stack.push(result, sign);13 result = 0;14 sign = 1;15 } else if (c === ')') {16 result += sign * num;17 num = 0;18 const prevSign = stack.pop();19 const prevResult = stack.pop();20 result = prevResult + prevSign * result;21 }22 }23 return result + sign * num;24};
Edge Cases & Common Mistakes
- Multi-digit numbers: build them with num = num × 10 + digit; adding each digit separately breaks 12 into 1 and 2.
- Forgetting the last number: the final number is never followed by an operator, so add sign × num after the loop.
- Popping in the wrong order: the sign was pushed last, so pop it first, then the outer sum.
- Unary minus: works without a special case, because the number before it is 0.
- Spaces: skip them; they can appear anywhere between tokens.
Summary
Keep a running sum with the sign of the next number. At '(' push the sum and sign and restart; at ')' fold the inner sum back with outer + sign × inner. Add the last number at the end. O(n) time, O(n) space for deeply nested brackets.
More practice: DSA interview questions with answers · patterns cheat sheet
