题目要求:
现基本计算器以计算简单表达式字符串。
表达式字符串可以包含左括号(和右括号)、加号+或减号、非负整数和空格。
表达式字符串只包含非负整数、+、-、*、/运算符、左括号和空格。整数除法应该截断为零。
您可以假定给定的表达式总是有效的。所有中间结果将在范围内[-2147483648,2147483647]
“1 + 1” = 2
" 6-4 / 2 " = 4
“2*(5+52)/3+(6/2+8)" = 21
"(2+6 3+5- (3*14/7+2)*5)+3”=-12
本来想用go实现,但是go没有直接可操作的栈,同时也不是很熟练,而python处理这种算法更简单,所以用了python实现。
解题思路:
先将表达式转为后缀表达式,然后做计算,因为后缀表达式计算更简单。同时,该程序还适合没有括号的表达式。
程序步骤
1、遇到空格,跳过不处理
2、遇到运算数,直接输出
3、若是左括号,将其压入栈
4、若遇到右括号,表明括号内的中缀表达式已经扫描完毕,将栈顶的运算符弹出并输出,直到遇倒左括号(左括号也出栈,但不输出)
5、若遇到运算符,若该运算符的优先级大于栈顶的运算符的优先级,则把它入栈;
若在运算符的优先级小于或等于栈顶运算符时,将栈顶运算符弹出并输出,再比较新的栈顶运算符,按同样处理方法,知道该运算符大于栈顶运算符优先级或者栈空为止,然后将该运算符入栈
6、若中缀表达式中的各对象处理完毕,则把堆栈中存留的运算符一并输出
代码实现
tips:代码没有做优化处理,也没经过LeetCode的验证(需要会员)
class Solution:
def calculate(self, s: str) -> int:
ret = []
s_list = self.cover_postfix(s)
for i in s_list:
if self.is_opt(i):
n2 = ret.pop()
n1 = ret.pop()
ret.append(self.fet_and_call(n1, n2, i))
else:
ret.append(int(i))
return ret.pop()
def fet_and_call(self, a: int, b: int, ops: str) -> int:
if ops == '*':
return int(a * b)
if ops == '/':
return int(a / b)
if ops == '+':
return int(a + b)
if ops == '-':
return int(a - b)
def cover_postfix(self, s: str) -> list:
"""中缀表达式转后缀表达式。操作符利用了单调栈处理"""
i = 0
s_len = len(s)
ret = [] # 存储表达式结果
ops = [] # 运算符栈
while i < s_len:
val = s[i]
if val == ' ': # 处理空格
i += 1
continue
if self.is_digit(val): # 处理运算数
n = 0
while i < s_len and self.is_digit(s[i]):
n = n * 10 + int(s[i])
i += 1
ret.append(str(n))
else: # 处理运算符和括号
if val == '(': # 处理左括号
ops.append(val)
elif val == ')': # 处理右括号
while ops and ops[-1] != '(':
ret.append(ops.pop())
ops.pop() # 左括号弹出不做输出
elif not ops or self.is_priority(val, ops[-1]): # 与栈顶先比优先级高则入栈
ops.append(val)
else:
# 比栈顶优先级低或者相等,直接入栈,直到遇到左括号或比该元素优先级高的栈顶元素,或者空栈的情况
while ops and self.is_priority(ops[-1], val) and val != '(':
ret.append(ops.pop())
# 入栈该元素
ops.append(val)
i += 1
# 若中缀表达式中的各对象处理完毕,则把堆栈中存留的运算符一并输出
while ops:
ret.append(ops.pop())
return ret
def is_digit(self, s: str) -> bool:
return '0' <= s <= '9'
def is_priority(self, a: str, b: str) -> bool:
return (a == '*' or a == '/') and (b == '+' or b == '/')
def is_opt(self, s: str) -> bool:
return s in ['+', '-', '*', '/']
s = Solution()
exp = "(2+6* 3+5- (3*14/7+2)*5)+3"
# res = s.cover_postfix(exp)
res = s.calculate(exp)
print(res)