小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
表达式求值
问题描述
请写一个整数计算器,支持加减乘三种运算和括号。
示例:
输入:"(2 * (3 - 4)))* 5"
返回值:-10
分析问题
因为只支持加、减、乘、括号,所以我们根据优先级可以分为3类,即括号>乘>加、减,假设先把括号去掉,那么就剩下乘和加减运算,根据运算规则,我们需要先计算乘、再计算加、减,因此我们可以这么来考虑,我们先进行乘法运算,并将这些乘法运算后的整数值返回原表达式的相应位置,则随后整个表达式的值,就等于一系列整数加减后的值。而对于被括号分割的表达式,我们可以递归的去求解,具体算法如下。
遍历字符串s,并用变量preSign记录每个数字之前的运算符,初始化为加号。
- 遇到空格时跳过。
- 遇到数字时,继续遍历求出这个完整的数字的值,保存到num中。
- 遇到左括号时,需要递归的求出这个括号内的表达式的值。
- 遇到运算符或者表达式的末尾时,就根据上一个运算符的类型来决定计算方式。
- 如果是加号,不需要进行计算,直接push到栈里
- 如果是减号,就去当前数的相反数,push到栈里
- 如果是乘号,就需要从栈内pop出一个数和当前数求乘法,再把计算结果push到栈中
- 最后把栈中的结果求和即可。
下面我们来看一下代码实现。
class Solution:
def calculate(self, s):
n = len(s)
#存取部分数据和
stack = []
preSign = '+'
num = 0
i=0
while i<n:
c=s[i]
if c==' ':
i=i+1
continue
if c.isdigit():
num = num * 10 + ord(c) - ord('0')
#如果遇到左括号,递归求出括号内表达式的值
if c=='(':
j=i+1
counts=1
#截取出括号表达式的值
while counts>0:
if s[j]=="(":
counts=counts+1
if s[j]==")":
counts=counts-1
j=j+1
#剥去一层括号,求括号内表达式的值
num=self.calculate(s[i+1:j-1])
i=j-1
if not c.isdigit() or i==n-1:
if preSign=="+":
stack.append(num)
elif preSign=="-":
stack.append(-1*num)
elif preSign=="*":
tmp=stack.pop()
stack.append(tmp*num)
num=0
preSign=c
i=i+1
return sum(stack)
s=Solution()
print(s.calculate("(3+4)*(5+(2-3))"))