Home
DSA Patterns
Stack
Basic Calculator II
Basic Calculator II
Evaluate an expression with + - * / and no parentheses in one pass: a stack of terms where * and / are applied to the top right away.
Problem Understanding
Basic Calculator II: evaluate a valid expression string containing non-negative integers, +, -, *, / and spaces, with no parentheses. Integer division truncates toward zero. Built-in eval is not allowed.
Example: "3+2*2" returns 7, because 2*2 is done before the addition.
The Intuition: Multiply Now, Add Later
Precedence says * and / bind tighter than + and -. A stack of terms to add handles that in one pass:
- Read digits into
num. - When an operator (or the end) arrives,
numis complete. Look at the operator before it,op:+: pushnum;-: push-num. These wait.*or/: pop the top, combine it withnum, push the result. These happen now.
- Set
opto the new operator and resetnum. - Sum the stack.
Starting with op = '+' makes the first number an ordinary push. Compare Evaluate Reverse Polish Notation, where the order of operations is already spelled out.
Interactive Walkthrough
The expression is on top, one character per cell; a space is drawn as ␣. Below it are the terms on the stack. Watch num grow digit by digit, then get pushed or folded into the top when the next operator arrives.
Dry Run Table
Input: "14-3/2"
| Char | num | op before | Action | Stack after |
|---|---|---|---|---|
| 1, 4 | 14 | + | — | [] |
| - | 14 | + | push 14 | [14] |
| 3 | 3 | - | — | [14] |
| / | 3 | - | push -3 | [14, -3] |
| 2 (end) | 2 | / | -3 / 2 = -1 | [14, -1] |
Answer: 14 + (-1) = 13.
The Solution Template
A stack of terms, the number being read, and the operator in front of it. Java and C need / on ints, which already truncates toward zero; Python and JavaScript truncate explicitly.
Basic Calculator II Code
1var calculate = function(s) {2 const stack = [];3 let num = 0, op = '+';4 for (let i = 0; i < s.length; i++) {5 const c = s[i];6 if (c >= '0' && c <= '9') num = num * 10 + Number(c);7 if ((c !== ' ' && !(c >= '0' && c <= '9')) || i === s.length - 1) {8 if (op === '+') stack.push(num);9 else if (op === '-') stack.push(-num);10 else if (op === '*') stack.push(stack.pop() * num);11 else stack.push(Math.trunc(stack.pop() / num));12 op = c;13 num = 0;14 }15 }16 return stack.reduce((a, b) => a + b, 0);17};
Edge Cases & Common Mistakes
- Multi-digit numbers: build
numacross characters; do not treat each digit as a number. - Spaces: skip them, but still finish the last number when the string ends in a space or a digit (
i == n - 1). - Negative division:
-3 / 2must be-1. Python's//gives-2; useint(a / b). - Using the current operator: the action belongs to the operator before the number; keep
opone step behind. - Overflow: intermediate products fit in 32 bits for LeetCode's inputs; C++ and C keep
numaslongwhile it is read.
Summary
Read numbers digit by digit. When a number ends, the operator before it decides: push it, push its negation, or fold it into the top with * or /. Only additions remain, so return the sum of the stack. O(n) time, O(n) space, or O(1) with a running total.
More practice: DSA interview questions with answers · patterns cheat sheet
