Date and Time: Oct 12, 2024, 11:28 (EST)
Link: https://leetcode.com/problems/basic-calculator/
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: 2
Example 2:
Input: s = " 2-1 + 2 "
Output: 3
Example 3:
Input: s = "(1+(4+5+2)-3)+(6+8)"
Output: 23
-
1 <= s.length <= 3 * 10^5 -
sconsists 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.
For each operation, we save the previous operation into three variables, then when we have a new operation, we update res with the previous operation with sign, num.
-
Use three variables
num, sign, resto keep track of values, andstack[]for"(". -
Four cases to consider:
i. when
i.isdigit(), we want to add this number tonumsince this variable keep track of a number before any operation, and we also need to consider a case that a number has more than one digit (23).ii. when
i in "+-", we need to first updateres += sign * num(process the operation before this new operation fromsign, num), then we change the sign to be-1 or 1depends oni == "-"or not, and we need to resetnum = 0, so we can take next number intonum.iii. when
i == "(", we need to appendstack[res, sign]into stack, so after we process all the operations within(), we can add or subtract the previousres.iv. when
i == ")", we can popres, signfromstack[]and updateresaccordingly. Lastly, resetnum = 0so we can retake new value intores. -
Finally, return
res + sign * numjust in case we have cases likes = "1 + 1".
class Solution:
def calculate(self, s: str) -> int:
# use res, sign, curr to keep track of current operation
# When we encounter a new sign, update res with prev operation, then update sign
# When encounter "(", save res, sign, into stack[], reset all variables
# When encounter ")", update the last operation result, pop sign, res from stack[], then reset variables
# TC: O(n), n = len(s), SC: O(n)
stack = []
res, sign, curr = 0, 1, 0
for i in s:
if i.isdigit():
curr = curr * 10 + int(i)
elif i in "+-":
res += sign * curr
sign = 1 if i == '+' else -1
curr = 0
elif i == "(":
stack.append(res)
stack.append(sign)
res, sign, curr = 0, 1, 0
elif i == ")":
res += sign * curr
res *= stack.pop()
res += stack.pop()
sign, curr = 1, 0
return res + sign * currTime Complexity:
Space Complexity:
Jun 20, 2026
When deal with "()", I save all intermediate results into stack = [prev, sign, curr], then when encounter ")", we update prev = oldSign * prev (current) + oldPrev to handle edge case "1-(-2)".
class Solution:
def calculate(self, s: str) -> int:
# Q: 1. Change sign
# 2. Parentheses
# S: 1. Keep checking either s[i] is digit or sign or parenthese
# 2. If digit: update digit, 2, 23
# 3. If sign: Save the previous sign with digit, by default, we should get + and 0
# 4. If parenthese: "(", save the previous digit and sign
# ")": pop from stack
# TC: O(n), n=len(s), SC: O(n)
stack = []
prev, sign, curr = 0, 1, 0
for i in s:
# Classify i
if i.isdigit():
curr = curr * 10 + int(i)
elif i in "+-":
# Update results into prev and update sign, reset curr
prev += sign * curr
if i == '-':
sign = -1
else:
sign = 1
curr = 0
elif i == "(":
stack.append(prev)
stack.append(curr)
stack.append(sign)
# Reset for calculation within ()
prev, sign, curr = 0, 1, 0
elif i == ")":
# Calculate current result, then add back with value saved in stack
prev += sign * curr
oldSign = stack.pop()
oldCurr = stack.pop()
oldPrev = stack.pop()
prev = oldSign * prev + oldCurr + oldPrev
# Reset sign and curr again
sign, curr = 1, 0
# Handle the last part
prev += sign * curr
return prevTime Complexity:
Space Complexity: