题目描述:
读入一个只包含’+‘、’-‘、’*‘、’/‘的非负整数计算表达式,计算该表达式的值

解题思路:

  1. 将给定的中缀表达式转换为后缀表达式 计算后缀表达式
  2. 通过第一步得到的后缀表达式计算结果

步骤1:中缀表达式转后缀表示:

  1. 设立一个操作符栈,用于临时存放操作符。设立另一个list,存放后缀表达式
  2. 从左至右扫描表达式,如果碰到数,就把操作数加入到后缀表达式中(注意:数字可能不止一位,例如’234’,需要读入下一位然后进行合并)
  3. 若碰到操作符,就与当前操作符栈栈顶的操作符的优先级进行比较。1>若当前的操作符优先级高于栈顶操作符的优先级,则将当前的操作符压栈。2>若当前操作符的优先级小于或等于栈顶操作符的优先级,则将操作符栈中的栈顶操作符出栈,直到遇到优先级高于当前操作符的。
  4. 重复上述操作,直至扫描完表达式。

步骤2:

  1. 从左至右遍历后缀表达式,如果是操作数,就跳过,如果是操作符,则取出操作符之前的两个数字。注意两个数字的顺序,在减法跟除法中是有顺序的区别的。
  2. 当前计算的结果替换取出两个数字中的一个,弹出另一个和当前的操作符。
  3. 直至后缀表达式中只剩下一个元素的时候停止。

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时,通过前一为来判断是否进位,如果前一位是奇数,则舍去,反之则进一。所以在实际执行过程中,有些测试用例会无法通过,此时可以写一个保留位数的函数来解决。