题目描述:
读入一个只包含’+‘、’-‘、’*‘、’/‘的非负整数计算表达式,计算该表达式的值
解题思路:
- 将给定的中缀表达式转换为后缀表达式 计算后缀表达式
- 通过第一步得到的后缀表达式计算结果
步骤1:中缀表达式转后缀表示:
- 设立一个操作符栈,用于临时存放操作符。设立另一个list,存放后缀表达式
- 从左至右扫描表达式,如果碰到数,就把操作数加入到后缀表达式中(注意:数字可能不止一位,例如’234’,需要读入下一位然后进行合并)
- 若碰到操作符,就与当前操作符栈栈顶的操作符的优先级进行比较。1>若当前的操作符优先级高于栈顶操作符的优先级,则将当前的操作符压栈。2>若当前操作符的优先级小于或等于栈顶操作符的优先级,则将操作符栈中的栈顶操作符出栈,直到遇到优先级高于当前操作符的。
- 重复上述操作,直至扫描完表达式。
步骤2:
- 从左至右遍历后缀表达式,如果是操作数,就跳过,如果是操作符,则取出操作符之前的两个数字。注意两个数字的顺序,在减法跟除法中是有顺序的区别的。
- 当前计算的结果替换取出两个数字中的一个,弹出另一个和当前的操作符。
- 直至后缀表达式中只剩下一个元素的时候停止。
python代码如下
class Solution:
def Change(self, string):
priority = {'+': 1, '-': 1, '*': 2, '/': 2} # 优先级,‘-’、‘+’为一类 ‘/’、‘*’为一类
suffix = []
operateList = []
curPtr = 0
while curPtr < len(string):
if '0' <= string[curPtr] <= '9': # 如果是操作数
curNum = int(string[curPtr])
curPtr += 1
while curPtr < len(string) and '0' <= string[curPtr] <= '9':
curNum = curNum * 10 + int(string[curPtr])
curPtr += 1
suffix.append(curNum) # 这里将数字保存为字符,方便后续遍历处理
elif string[curPtr] == ' ':
curPtr += 1 # 如果是空格,跳过
continue
else: # 如果是操作符
while len(operateList) != 0 and priority[string[curPtr]] <= priority[operateList[-1]]: # 如果当前操作符优先级小于或者等于栈顶操作符,则弹出栈顶元素,直到优先级大于当前操作符位置
suffix.append(operateList[-1])
operateList.pop()
operateList.append(string[curPtr])
curPtr += 1
while len(operateList) != 0: # 如果操作符栈非空,则直接弹出剩下的操作符
suffix.append(operateList[-1])
operateList.pop()
return suffix
def calculate(self, s: str) -> int:
if not s: return 0
suffix = self.Change(s)
curPtr = 0
while len(suffix) > 1:
if isinstance(suffix[curPtr], int): # 如果是数字,继续
curPtr += 1
else: # 如果不是数字,就一定为操作符
num1 = int(suffix[curPtr - 2]) # 取操作符前面的两个数字,curPtr-2为第一操作数, curPtr-1为第二操作说,在减法跟乘法中会有区别
num2 = int(suffix[curPtr - 1]) # 这里要使用float类型的转化,因为在除法中,会产生小数
res = 0
curOperate = suffix[curPtr]
if curOperate == '+':
res = num1 + num2
if curOperate == '-':
res = num1 - num2
if curOperate == '*':
res = num1 * num2
if curOperate == '/':
res = num1 // num2
suffix[curPtr - 1] = res # 将curPtr-1位置处的数字替换为结果,pop curPtr-2处的数字
suffix.pop(curPtr-2)
suffix.pop(suffix.index(curOperate)) # 弹出操作符
curPtr = 0
return suffix[0]
在python代码中,对于小数取舍的函数 round(num, 保留位数),round()函数的思想是四舍六入五留双,意思就是小于等于4舍去,大于等于6进1,当前位置是5时,通过前一为来判断是否进位,如果前一位是奇数,则舍去,反之则进一。所以在实际执行过程中,有些测试用例会无法通过,此时可以写一个保留位数的函数来解决。