topic:
https://leetcode-cn.com/problems/basic-calculator/
Calculator implemented to calculate a basic value of a simple string expression.
String expressions may comprise a left parenthesis (right parenthesis), plus +, minus -, space and non-negative integers.
Example 1:
Input: "1 + 1"
Output: 2
Example 2:
Input: "2-1 + 2"
Output: 3
Example 3:
Input: "(1 + (4 + 5 + 2) -3) + (6 + 8)"
Output: 23
Description:
You may assume that the given expression is valid.
Do not use the built-in library functions eval.
Problem-solving ideas
- Wanted to use FSM, later found to have no need.
- Operator presence within a stack, each element comprising operator, and a priority,
- Digital placed inside another stack, for convenience, into plastic.
- When I see "(" current priority will +1 met ")" will be priority of -1.
- The foundation refining operations as a function to facilitate multiple calls
- Note Scan to last, we need to consider whether the figures are pushed onto the stack
- Full scan unit characters one by one will need to eject calculation operators in the operator stack
- Finally, there is the result of a digital stack should be the only one
- Description invalid because the topics will not be the case, there is no need to consider an exception case
Code
class Solution:
def calculate(self, s: str) -> int:
number = '' # - current number
level = 0 # - current op level
number_stack = [] # - int number stack
op_stack = [] # - element as (op,level)
# - pop 2 numbers and 1 op, and do once calculate
def calc_op():
op, _ = op_stack.pop()
right = number_stack.pop()
left = number_stack.pop()
if op == '+':
number_stack.append(left + right)
elif op == '-':
number_stack.append(left - right)
else:
pass
# - scan chars in s
for c in s:
if '0' <= c <= '9':
# - update number
number += c
else:
# - push number in number_stack
if number:
number_stack.append(int(number))
number = ''
if c in ['+', '-']:
# - check operator level with op_stack[-1],
# - if current level is not greater than op in stack,
# - calculate the op in stack
while op_stack and (op_stack[-1][1] >= level):
calc_op()
# - push current op in op_stack
op_stack.append((c, level))
elif c == '(':
level += 1
elif c == ')':
level -= 1
else:
pass
# - if end with number
if number:
number_stack.append(int(number))
# - check if still has op to calc
while op_stack:
calc_op()
return number_stack[0]