简单四则运算解析器| 豆包MarsCode AI 刷题

128 阅读3分钟

题目分析

根据所给题目,可知问题是要求我们实现一个计算器来计算简单的字符串表达式。因为表达式中可以包含加、减、乘、除以及括号,所以我们需要根据运算优先级和括号来正确地计算结果。栈先进后出的特点就可以很好地处理括号、运算符和数字,故我们可以使用栈来帮助我们处理这个问题。

思路

  • 使用两个栈:

    1. ops栈用来保存运算符。
    2. nums栈用来保存数值。
  • 遇到数字时,直接加入nums

  • 遇到运算符时,根据运算符的优先级来决定是否进行运算:

    • 如果当前运算符优先级比栈顶运算符低,就先执行栈顶运算符的运算
  • 遇到括号时,遇到左括号进入递归,遇到右括号时计算当前括号内的内容

解题步骤

1.数字的提取:需要通过遍历字符串来识别数字

2.运算符的处理:加法、减法、乘法和除法需要按照优先级来处理,乘除法的优先级高于加减法

3.括号的处理:当遇到括号时,可以递归地求解括号内的子表达式

4.整数除法:按照题意,除法应该返回整数结果,即执行整数除法

复杂度分析:

1.时间复杂度: O(n),其中n是表达式的长度。每个字符至多被处理一次,栈的操作(压入和弹出)也是O(1)的

2.空间复杂度: O(n),用于存储运算符和数字的栈

具体实现

def solution(expression):
    def apply_operator(oper, b, a):
        if oper == '+':
            return a + b
        elif oper == '-':
            return a - b
        elif oper == '*':
            return a * b
        elif oper == '/':
            # 执行整数除法
            return a // b if a * b >= 0 else -(abs(a) // abs(b))
    
    def precedence(op):
        if op == '+' or op == '-':
            return 1
        if op == '*' or op == '/':
            return 2
        return 0
    
    ops = []  # 运算符栈
    nums = []  # 数字栈
    i = 0
    n = len(expression)
    
    while i < n:
        if expression[i] == ' ':
            i += 1
            continue
        if expression[i] == '(':
            ops.append('(')
            i += 1
        elif expression[i] == ')':
            # 处理括号内的表达式
            while ops and ops[-1] != '(':
                op = ops.pop()
                right = nums.pop()
                left = nums.pop()
                nums.append(apply_operator(op, right, left))
            ops.pop()  # 弹出 '('
            i += 1
        elif expression[i] in '+-*/':
            # 处理运算符
            while (ops and ops[-1] != '(' and 
                   precedence(ops[-1]) >= precedence(expression[i])):
                op = ops.pop()
                right = nums.pop()
                left = nums.pop()
                nums.append(apply_operator(op, right, left))
            ops.append(expression[i])
            i += 1
        else:
            # 处理数字,可能是多位数
            num = 0
            while i < n and expression[i].isdigit():
                num = num * 10 + int(expression[i])
                i += 1
            nums.append(num)
    
    # 最后处理栈中的剩余运算符
    while ops:
        op = ops.pop()
        right = nums.pop()
        left = nums.pop()
        nums.append(apply_operator(op, right, left))
    
    return nums[0]

#测试
if __name__ == "__main__":
    print(solution("1+1") == 2)
    print(solution("3+4*5/(3+2)") == 7)
    print(solution("4+2*5-2/1") == 12)
    print(solution("(1+(4+5+2)-3)+(6+8)") == 23)

代码说明

  • apply_operator: 用来执行加、减、乘、除运算。要注意的是,除法使用了整数除法,并处理了负数除法的情况
  • precedence: 判断运算符的优先级,*/优先级高于+-
  • 主循环:
    • 处理括号:遇到左括号时,将其压入运算符栈;遇到右括号时,直到遇到左括号为止,逐个执行栈中的运算符。
    • 处理运算符:当遇到一个运算符时,先判断它的优先级,并决定是否执行栈中的运算符。
    • 处理数字:通过遍历字符,获取连续的数字并转换成整数。
  • 最后: 当所有字符都被处理后,栈中可能还剩下运算符,我们需要继续计算剩下的运算