Basic Calculator
HardPrompt
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().
Example 1:
Input: s = "1 + 1"
Output: 2Example 2:
Input: s = " 2-1 + 2 "
Output: 3Example 3:
Input: s = "(1+(4+5+2)-3)+(6+8)"
Output: 23
Constraints:
1 <= s.length <= 3 * 105sconsists of digits,'+','-','(',')', and' '.srepresents a valid expression.'+'is not used as a unary operation (i.e.,"+1"and"+(2 + 3)"is invalid).'-'could be used as a unary operation (i.e.,"-1"and"-(2 + 3)"is valid).- There will be no two consecutive operators in the input.
- Every number and running calculation will fit in a signed 32-bit integer.
Approaches
2 approaches with complexity analysis and trade-offs.
We can solve this problem using two stacks - one for numbers and one for operators. We process the expression character by character and handle parentheses by evaluating sub-expressions.
Algorithm
- Initialize two stacks: nums for numbers and ops for operators
- Iterate through each character in the string:
- Skip spaces
- Parse complete numbers when digits are found
- Handle opening parenthesis by pushing to ops stack
- Handle closing parenthesis by evaluating sub-expression
- Handle operators by evaluating previous operations
- Process remaining operations in the stack
- Return final result
Walkthrough
This approach uses two stacks to evaluate the expression:
- First, we initialize two stacks - nums for numbers and ops for operators
- We iterate through each character in the string:
- Skip spaces
- If we find a digit, parse the complete number
- If we find an opening parenthesis '(', push it to ops stack
- If we find a closing parenthesis ')', evaluate everything until matching '('
- If we find an operator (+/-), evaluate all higher or equal precedence operations before pushing
Here's the implementation:
public int calculate(String s) { Stack<Integer> nums = new Stack<>(); Stack<Character> ops = new Stack<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == ' ') continue; if (Character.isDigit(c)) { int num = c - '0'; while (i + 1 < s.length() && Character.isDigit(s.charAt(i + 1))) { num = num * 10 + (s.charAt(i + 1) - '0'); i++; } nums.push(num); } else if (c == '(') { ops.push(c); } else if (c == ')') { while (!ops.isEmpty() && ops.peek() != '(') { nums.push(applyOp(ops.pop(), nums.pop(), nums.pop())); } ops.pop(); // Remove '(' } else if (c == '+' || c == '-') { while (!ops.isEmpty() && ops.peek() != '(') { nums.push(applyOp(ops.pop(), nums.pop(), nums.pop())); } ops.push(c); } } while (!ops.isEmpty()) { nums.push(applyOp(ops.pop(), nums.pop(), nums.pop())); } return nums.pop();} private int applyOp(char op, int b, int a) { switch (op) { case '+': return a + b; case '-': return a - b; default: return 0; }}Complexity
Time
O(n) where n is the length of the input string. We process each character once.
Space
O(n) where n is the length of the input string. In worst case, we might need to store all numbers and operators in the stacks.
Trade-offs
Pros
Easy to understand and implement
Can handle nested parentheses
Straightforward approach for basic calculator operations
Cons
Uses extra space for two stacks
Requires multiple stack operations
Not as efficient as single pass solutions
Solutions
Solution
public class Solution { public int Calculate(string s) { var stk = new Stack < int > (); int sign = 1; int n = s.Length; int ans = 0; for (int i = 0; i < n; ++i) { if (s[i] == ' ') { continue; } if (s[i] == '+') { sign = 1; } else if (s[i] == '-') { sign = -1; } else if (s[i] == '(') { stk.Push(ans); stk.Push(sign); ans = 0; sign = 1; } else if (s[i] == ')') { ans *= stk.Pop(); ans += stk.Pop(); } else { int num = 0; while (i < n && char.IsDigit(s[i])) { num = num * 10 + s[i] - '0'; ++i; }--i; ans += sign * num; } } return ans; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.