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

35 阅读3分钟

问题描述

小F面临一个编程挑战:实现一个基本的计算器来计算简单的字符串表达式的值。该字符串表达式有效,并可能包含数字(0-9)、运算符+-及括号()。注意,字符串中不包含空格。除法运算应只保留整数结果。请实现一个解析器计算这些表达式的值,且不使用任何内置的eval函数。


测试样例

样例1:

输入:expression = "1+1"
输出:2

样例2:

输入:expression = "3+4*5/(3+2)"
输出:7

思路

我们的目标是解析并计算一个包含数字、加减乘除运算符以及括号的字符串表达式。为了实现这一点,我们需要处理以下几个关键点:

1. 数据结构选择

我们使用两个栈来帮助解析和计算表达式:

  • 数值栈 (values) :用于存储中间计算结果和最终结果。
  • 运算符栈 (operators) :用于存储待处理的运算符。

2. 处理数字

当我们遇到数字时,需要将其完整地读取出来并转换为整数,然后压入数值栈。这是因为数字可能不止一位,例如 "123" 应该被解析为一个整体的数字 123。

3. 处理运算符

运算符的处理需要考虑优先级。我们使用一个辅助函数 greater_precedence 来比较运算符的优先级:

  • 如果当前运算符的优先级高于或等于栈顶运算符的优先级,我们先计算栈顶的运算符。
  • 否则,我们将当前运算符压入运算符栈。

4. 处理括号

括号用于改变运算的优先级:

  • 当遇到左括号 ( 时,直接将其压入运算符栈。
  • 当遇到右括号 ) 时,不断弹出运算符栈中的运算符并计算,直到遇到左括号 (,然后将左括号从栈中弹出。

5. 计算结果

  • 遍历完表达式后,可能还会剩下一些运算符在栈中,继续计算直到运算符栈为空。
  • 最终,数值栈中应该只剩下一个值,即表达式的计算结果。

具体实现

下面是详细的实现步骤和代码:

辅助函数

  1. apply_operator:执行运算符对应的数学运算,并将结果存回数值栈中。
  2. greater_precedence:比较运算符的优先级。
def apply_operator(operators, values):
    operator = operators.pop()
    right = values.pop()
    left = values.pop()
    if operator == '+':
        values.append(left + right)
    elif operator == '-':
        values.append(left - right)
    elif operator == '*':
        values.append(left * right)
    elif operator == '/':
        values.append(int(left / right))  # 整数除法

def greater_precedence(op1, op2):
    precedence = {'+': 1, '-': 1, '*': 2, '/': 2}
    return precedence[op1] >= precedence[op2]

主函数

  1. 初始化两个栈:数值栈 values 和运算符栈 operators

  2. 遍历表达式中的每个字符:

    • 如果是数字,读取完整数字并压入数值栈。
    • 如果是左括号 (,压入运算符栈。
    • 如果是右括号 ),计算直到遇到左括号 (
    • 如果是运算符,根据优先级决定是否先计算栈顶的运算符,然后将当前运算符压入运算符栈。
  3. 遍历完表达式后,继续计算剩余的运算符。

  4. 返回数值栈中唯一的值作为结果。

def solution(expression):
    operators = []
    values = []
    i = 0
    while i < len(expression):
        if expression[i].isdigit():
            val = 0
            while i < len(expression) and expression[i].isdigit():
                val = val * 10 + int(expression[i])
                i += 1
            values.append(val)
            continue
        if expression[i] == '(':
            operators.append(expression[i])
        elif expression[i] == ')':
            while operators[-1] != '(':
                apply_operator(operators, values)
            operators.pop()  # 弹出 '('
        else:
            while operators and operators[-1] != '(' and greater_precedence(operators[-1], expression[i]):
                apply_operator(operators, values)
            operators.append(expression[i])
        i += 1

    while operators:
        apply_operator(operators, values)

    return values[0]