华为OD机考双机位C卷 - 仿LISP运算 (Java & Python & JS & GO & C++ & C)

4 阅读4分钟

仿LISP运算

2026华为OD机试双机位C卷 - 华为OD上机考试双机位C卷

华为OD机试双机位C卷真题目录点击查看: 【全网首发】2026华为OD机位C卷 机考真题题库含考点说明以及在线OJ(OD上机考试双机位C卷)

题目描述

LISP 语言唯一的语法就是括号要配对。

形如 (OP P1 P2 …),括号内元素由单个空格分割。

其中第一个元素 OP 为操作符,后续元素均为其参数,参数个数取决于操作符类型。

注意:

参数 P1, P2 也有可能是另外一个嵌套的 (OP P1 P2 …) ,当前 OP 类型为 add / sub / mul / div(全小写),分别代表整数的加减乘除法,简单起见,所有 OP 参数个数均为 2 。

举例:

  • 输入:(mul 3 -7)输出:-21

  • 输入:(add 1 2) 输出:3

  • 输入:(sub (mul 2 4) (div 9 3)) 输出 :5

  • 输入:(div 1 0) 输出:error

题目涉及数字均为整数,可能为负;

不考虑 32 位溢出翻转,计算过程中也不会发生 32 位溢出翻转,

除零错误时,输出 “error”,

除法遇除不尽,向下取整,即 3/2 = 1

输入描述

输入为长度不超过512的字符串,用例保证了无语法错误

输出描述

输出计算结果或者“error”

示例1

输入

(div 12 (sub 45 45))

输出

error

说明

示例2

输入

(add 1 (div -7 3))

输出

-2

说明

73+1=43-\frac{7}{3} + 1 = -\frac{4}{3}

向下取整(floor)结果为:

43=2\lfloor -\frac{4}{3} \rfloor = -2

解题思路

题目分析

题目要求解析并计算一个仿 LISP 语言的表达式。 表达式的格式是 (OP P1 P2),其中 OP 是操作符(add, sub, mul, div),P1P2 是参数,可能是整数,也可能是嵌套的表达式。 我们需要处理嵌套的括号结构,计算出最终结果。 题目还特别提到了一些细节:

  1. 除法:除不尽时向下取整(例如 3/2=13/2 = 1, 4/3=2-4/3 = -2)。
  2. 错误处理:除以 0 时输出 "error"。
  3. 整数范围:不会发生 32 位溢出。

解题策略:双栈法

这类嵌套表达式求值问题,经典的解法是使用栈 (Stack)。 我们可以使用两个栈:

  1. 操作符栈 (operaStack):用于存储操作符(add, sub, mul, div)。
  2. 数字栈 (numStack):用于存储操作数和中间计算结果。

算法流程

遍历输入字符串的每一个字符:

  1. 遇到左括号 (

    • 这意味着一个新的表达式开始了。
    • 紧接着左括号的 3 个字符一定是操作符(add, sub, mul, div)。
    • 将操作符提取出来,压入 operaStack
    • 跳过操作符,继续处理后续字符。
  2. 遇到右括号 )

    • 这意味着一个当前层的表达式结束了。
    • 在遇到右括号之前,如果有未处理的数字字符串,先将其解析为整数并压入 numStack
    • 此时,numStack 的栈顶两个元素分别是该表达式的参数 P2P2P1P1(注意栈是后进先出,所以先弹出的是 P2P2)。
    • operaStack 弹出对应的操作符。
    • 执行计算:result = calc(op, P1, P2)
    • 将计算结果 result 压回 numStack,作为外层表达式的一个参数。
  3. 遇到空格

    • 空格是分隔符。
    • 如果在空格之前有未处理的数字字符串,将其解析为整数并压入 numStack
  4. 遇到数字或负号

    • 记录数字字符串的起始位置,直到遇到空格或右括号为止。

关键细节处理

  1. 除法向下取整

    • 在 C++/Java 中,整数除法 /向零取整(截断)。
    • 例如:3 / 2 = 1(正确),-4 / 3 = -1(错误,题目要求向下取整,应为 -2)。
    • 对于负数除法,如果不能整除,需要额外减 1。
    • Python 的 // 操作符和 math.floor 默认就是向下取整,处理起来比较方便。
    • JavaScript 的 Math.floor 也是向下取整。
  2. 除以零

    • 在执行除法前检查除数是否为 0。如果是,直接输出 "error" 并结束程序。
  3. 解析数字

    • 由于输入中可能有空格,解析数字时需要维护一个指针或标记,提取完整的数字字符串(包括负号)。