LeetCode Templates: Calculator Problems
Contents
- Basic Calculator (+, -, parentheses)
- Basic Calculator II (+, -, *, /)
- Basic Calculator III (All operators + parentheses)
- Common Patterns
- Comparison Table
Basic Calculator (+, -, parentheses)
Handles addition, subtraction, and parentheses. Use stack to save state before entering parentheses.
int calculate(string s) {
stack<int> stk;
int result = 0, num = 0, sign = 1;
for(char c: s) {
if(isdigit(c)) {
num = num * 10 + (c - '0');
}
switch(c) {
case '+':
result += sign * num;
sign = 1;
num = 0;
break;
case '-':
result += sign * num;
sign = -1;
num = 0;
break;
case '(':
stk.push(result);
stk.push(sign);
sign = 1;
result = 0;
break;
case ')':
result += sign * num;
result *= stk.top(); stk.pop();
result += stk.top(); stk.pop();
num = 0;
break;
}
}
return result + (sign * num);
}
Key Points:
- Save
resultandsignbefore( - Apply saved
signand add to savedresultafter) - Track current
signfor each number
| ID | Title | Link | Solution |
|---|---|---|---|
| 224 | Basic Calculator | Link | Solution |
Basic Calculator II (+, -, *, /)
Handles all four operators without parentheses. Evaluate * and / immediately, defer + and -.
int calculate(string s) {
stack<int> stk;
char operation = '+';
int curr = 0;
for(int i = 0; i < s.length(); i++) {
char ch = s[i];
if(isdigit(ch)) {
curr = (curr * 10) + (ch - '0');
}
if((!isdigit(ch) && !isspace(ch)) || i == s.length() - 1) {
switch(operation) {
case '+':
stk.push(curr);
break;
case '-':
stk.push(-curr);
break;
case '*':
stk.top() *= curr;
break;
case '/':
stk.top() /= curr;
break;
}
operation = ch;
curr = 0;
}
}
int result = 0;
while(!stk.empty()) {
result += stk.top();
stk.pop();
}
return result;
}
Key Points:
- Evaluate
*and/immediately (high precedence) - Defer
+and-by pushing to stack - Sum all stack elements at the end
Optimized Version (O(1) space):
int calculate(string s) {
int curr = 0, last = 0, result = 0;
char sign = '+';
for(int i = 0; i < s.length(); i++) {
char c = s[i];
if(isdigit(c)) {
curr = curr * 10 + (c - '0');
}
if((!isdigit(c) && !isspace(c)) || i == s.length() - 1) {
if(sign == '+' || sign == '-') {
result += last;
last = (sign == '+') ? curr : -curr;
} else if(sign == '*') {
last = last * curr;
} else if(sign == '/') {
last = last / curr;
}
sign = c;
curr = 0;
}
}
return result + last;
}
| ID | Title | Link | Solution |
|---|---|---|---|
| 227 | Basic Calculator II | Link | Solution |
Basic Calculator III (All operators + parentheses)
Combines all operators with parentheses. Use recursion or stack to handle nesting.
class Solution {
private:
int parseExpr(const string& s, int& idx) {
char op = '+';
vector<int> stk;
for(; idx < s.size(); idx++) {
if(isspace(s[idx])) continue;
long num = 0;
if(s[idx] == '(') {
num = parseExpr(s, ++idx);
} else if(isdigit(s[idx])) {
num = parseNum(s, idx);
idx--;
} else if(s[idx] == ')') {
break;
} else {
continue;
}
switch(op) {
case '+': stk.push_back(num); break;
case '-': stk.push_back(-num); break;
case '*': stk.back() *= num; break;
case '/': stk.back() /= num; break;
}
if(idx + 1 < s.size()) {
op = s[idx + 1];
}
}
int result = 0;
for(int num: stk) result += num;
return result;
}
long parseNum(const string& s, int& idx) {
long num = 0;
while(idx < s.size() && isdigit(s[idx])) {
num = num * 10 + (s[idx] - '0');
idx++;
}
return num;
}
public:
int calculate(string s) {
int idx = 0;
return parseExpr(s, idx);
}
};
Key Points:
- Recursion naturally handles nested parentheses
- Combine stack approach for operators with recursive approach for parentheses
- Evaluate
*and/immediately, defer+and-
| ID | Title | Link | Solution |
|---|---|---|---|
| 772 | Basic Calculator III | Link | Solution |
Common Patterns
1. Number Building
int num = 0;
for(char c: s) {
if(isdigit(c)) {
num = num * 10 + (c - '0');
}
}
2. Sign Tracking
int sign = 1; // 1 for positive, -1 for negative
// Apply: result += sign * num;
3. Operator Precedence
// High precedence: evaluate immediately
if(op == '*' || op == '/') {
// Immediate evaluation
} else {
// Defer to stack
}
4. Parentheses Handling
// Stack approach
if(c == '(') {
stk.push(result);
stk.push(sign);
result = 0;
sign = 1;
} else if(c == ')') {
result += sign * num;
result *= stk.top(); stk.pop();
result += stk.top(); stk.pop();
}
// Recursive approach
if(c == '(') {
num = parseExpr(s, ++idx);
}
Comparison Table
| Problem | Operators | Parentheses | Approach | Complexity |
|---|---|---|---|---|
| 224 | +, - |
✅ | Stack (save state) | O(n) time, O(n) space |
| 227 | +, -, *, / |
❌ | Stack or variables | O(n) time, O(n) or O(1) space |
| 772 | +, -, *, / |
✅ | Recursion + Stack | O(n) time, O(n) space |
Key Insights
- Operator Precedence:
*and/have higher precedence than+and- - Immediate vs Deferred: High precedence operators are evaluated immediately
- Parentheses: Create nested evaluation contexts - use stack or recursion
- Sign Propagation: Track signs through parentheses using stack
- Number Building: Accumulate digits to form multi-digit numbers
Related Problems
- 150. Evaluate Reverse Polish Notation - Postfix notation
- 394. Decode String - Nested structure processing
- 71. Simplify Path - Path processing with stack
Common Mistakes
- Forgetting final number: Not adding
sign * numat the end - Wrong operator precedence: Evaluating
+before* - Stack order: Pushing/popping in wrong order for parentheses
- Sign handling: Not applying saved sign correctly after
) - Number reset: Not resetting
numafter processing operators