from typing import List, Union
class Solution:
def calculate(self, s: str) -> int:
"""
T(n): O(n)
S(n): O(n)
该算法实现了对一般表达式的求值,支持运算符 + - * / ^ 以及分界符号( )
计算结果按照题目意思是 int, 如果需要将计算结果改为精度高的 float,需要去掉 cal_postfix_expression 里面的向零取证
"""
expression: List[str] = s2infix_expression_list(s)
postfix_expression = infix2postfix(expression)
return cal_postfix_expression(postfix_expression)
precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3}
def s2infix_expression_list(s: str) -> List[str]:
"""
将 s 转化成 list 类型的中缀表达式
"""
assert s is not None
infix_expression: List[str] = []
s = s.replace(' ', '')
i = 0
while i < len(s):
if s[i] in precedence or s[i] == '(' or s[i] == ')':
infix_expression.append(s[i])
i += 1
else:
j = i + 1
while j < len(s) and s[j].isdigit():
j += 1
infix_expression.append(s[i:j])
i = j
return infix_expression
def infix2postfix(infix: List[str]) -> List[str]:
"""
将 list 类型的中缀表达式转化成 list 类型的后缀表达式
栈 里面只存运算符和表达式
扫描到 ( 直接入栈
扫描到:运算符 + - * / ^
栈顶为 ( 或者栈为空,直接入栈
将栈里面的运算符弹出到栈顶运算符都比将要入栈的这个小
"""
postfix_expression: List[str] = []
operator_stack: List[str] = []
for item in infix:
if item.isdigit():
postfix_expression.append(item)
else:
if item == ')':
while operator_stack[-1] != '(':
postfix_expression.append(operator_stack.pop())
operator_stack.pop()
elif item == '(':
operator_stack.append(item)
# 表示 item 是运算符
else:
if len(operator_stack) == 0 or operator_stack[-1] == '(':
operator_stack.append(item)
else:
while len(operator_stack) > 0 and operator_stack[-1] in precedence and \
precedence[item] <= precedence[operator_stack[-1]]:
postfix_expression.append(operator_stack.pop())
operator_stack.append(item)
while len(operator_stack) > 0:
postfix_expression.append(operator_stack.pop())
return postfix_expression
def cal_postfix_expression(postfix_expression: List[str]) -> Union[float | int]:
"""
计算后缀表达式的值(向零去整:int(str_item))
"""
cal_stack: List[int] = []
for item in postfix_expression:
if item.isdigit():
cal_stack.append(int(item))
else:
b = cal_stack.pop()
a = cal_stack.pop()
if item == '+':
cal_stack.append(int(a + b))
elif item == '-':
cal_stack.append(int(a - b))
elif item == '*':
cal_stack.append(int(a * b))
elif item == '/':
cal_stack.append(int(a / b))
elif item == '^':
cal_stack.append(int(a ** b))
return cal_stack[0]
if __name__ == "__main__":
# 左边括号直接进入、右边括号弹出到遇到右括号
expression_str = "3 + 5 / 2"
s = Solution()
print(s.calculate(expression_str))