专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。
一、题目描述
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 |
二、输入描述
输入为长度不超过512的字符串,用例保证了无语法错误
三、输出描述
输出计算结果或者“error”。
四、测试用例
测试用例1
1、输入
(mul (sub 10 2) (add 1 2))
2、输出
24
3、说明
计算过程为 (10-2) * (1+2) = 8 * 3 = 24
测试用例2
1、输入
(div 10 0)
2、输出
error
3、说明
除数为0,抛出错误
五、解题思路
- 去除外层括号
- 提取操作符
- 解析两个参数(考虑嵌套括号)
- 递归计算参数值
- 根据操作符执行运算
- 处理除零异常
六、Python算法源码
# Python实现
def calculate(expr):
"""主计算函数"""
try:
result = evaluate(expr)
return str(result)
except Exception:
return "error"
def evaluate(expr):
"""递归求值函数"""
expr = expr.strip()
# 如果是纯数字,直接返回
if not expr.startswith("("):
return int(expr)
# 去掉外层括号
expr = expr[1:-1]
# 找到操作符
first_space = expr.find(' ')
op = expr[:first_space]
rest = expr[first_space + 1:]
# 解析两个参数
params = parse_params(rest)
param1 = evaluate(params[0])
param2 = evaluate(params[1])
# 根据操作符计算结果
if op == "add":
return param1 + param2
elif op == "sub":
return param1 - param2
elif op == "mul":
return param1 * param2
elif op == "div":
if param2 == 0:
raise ArithmeticError("除零错误")
return param1 // param2 # 整数除法
else:
raise ValueError(f"未知操作符: {op}")
def parse_params(rest):
"""解析参数,返回两个参数的列表"""
params = ["", ""]
level = 0
start = 0
param_index = 0
# 遍历字符串,根据括号层级分割参数
for i, c in enumerate(rest):
if c == '(':
level += 1
elif c == ')':
level -= 1
elif c == ' ' and level == 0:
# 当括号层级为0时,空格是参数分隔符
params[param_index] = rest[start:i]
param_index += 1
start = i + 1
if param_index == 2:
break
# 最后一个参数
if param_index < 2:
params[param_index] = rest[start:]
return params
# 主函数
if __name__ == "__main__":
expr = input()
print(calculate(expr))
七、JavaScript算法源码
// JavaScript实现
const readline = require('readline');
// 创建读取接口
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 主计算函数
function calculate(expr) {
try {
const result = evaluate(expr);
return String(result);
} catch (e) {
return "error";
}
}
// 递归求值函数
function evaluate(expr) {
expr = expr.trim();
// 如果是纯数字,直接返回
if (!expr.startsWith("(")) {
return parseInt(expr);
}
// 去掉外层括号
expr = expr.substring(1, expr.length - 1);
// 找到操作符
const firstSpace = expr.indexOf(' ');
const op = expr.substring(0, firstSpace);
const rest = expr.substring(firstSpace + 1);
// 解析两个参数
const params = parseParams(rest);
const param1 = evaluate(params[0]);
const param2 = evaluate(params[1]);
// 根据操作符计算结果
switch (op) {
case "add":
return param1 + param2;
case "sub":
return param1 - param2;
case "mul":
return param1 * param2;
case "div":
if (param2 === 0) {
throw new Error("除零错误");
}
return Math.floor(param1 / param2); // 整数除法
default:
throw new Error("未知操作符: " + op);
}
}
// 解析参数,返回两个参数的数组
function parseParams(rest) {
const params = ["", ""];
let level = 0;
let start = 0;
let paramIndex = 0;
// 遍历字符串,根据括号层级分割参数
for (let i = 0; i < rest.length; i++) {
const c = rest.charAt(i);
if (c === '(') {
level++;
} else if (c === ')') {
level--;
} else if (c === ' ' && level === 0) {
// 当括号层级为0时,空格是参数分隔符
params[paramIndex++] = rest.substring(start, i);
start = i + 1;
if (paramIndex === 2) {
break;
}
}
}
// 最后一个参数
if (paramIndex < 2) {
params[paramIndex] = rest.substring(start);
}
return params;
}
// 读取输入并处理
rl.on('line', (input) => {
console.log(calculate(input));
rl.close();
});
八、C算法源码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 函数声明
char* calculate(char* expr);
int evaluate(char* expr);
void parseParams(char* rest, char params[2][256]);
char* trim(char* str);
int findMatchingParen(char* str, int start);
// 主函数
int main() {
char input[512];
fgets(input, sizeof(input), stdin);
// 移除换行符
input[strcspn(input, "\n")] = 0;
// 计算结果
char* result = calculate(input);
printf("%s\n", result);
return 0;
}
// 主计算函数
char* calculate(char* expr) {
static char result[20];
// 尝试计算
int value = evaluate(expr);
// 如果返回值是特殊值-999999,表示错误
if (value == -999999) {
strcpy(result, "error");
} else {
sprintf(result, "%d", value);
}
return result;
}
// 递归求值函数
int evaluate(char* expr) {
expr = trim(expr);
// 如果是纯数字,直接返回
if (expr[0] != '(') {
return atoi(expr);
}
// 复制表达式以便修改
char temp[512];
strcpy(temp, expr);
// 去掉外层括号
int len = strlen(temp);
temp[len - 1] = '\0';
char* inner = temp + 1;
// 找到操作符
char* space = strchr(inner, ' ');
if (!space) return -999999;
*space = '\0';
char* op = inner;
char* rest = space + 1;
// 解析两个参数
char params[2][256];
parseParams(rest, params);
// 递归计算参数值
int param1 = evaluate(params[0]);
int param2 = evaluate(params[1]);
// 检查错误
if (param1 == -999999 || param2 == -999999) {
return -999999;
}
// 根据操作符计算结果
if (strcmp(op, "add") == 0) {
return param1 + param2;
} else if (strcmp(op, "sub") == 0) {
return param1 - param2;
} else if (strcmp(op, "mul") == 0) {
return param1 * param2;
} else if (strcmp(op, "div") == 0) {
if (param2 == 0) {
return -999999; // 除零错误
}
return param1 / param2;
} else {
return -999999; // 未知操作符
}
}
// 解析参数,分割成两个参数
void parseParams(char* rest, char params[2][256]) {
int level = 0;
int start = 0;
int paramIndex = 0;
int len = strlen(rest);
// 遍历字符串,根据括号层级分割参数
for (int i = 0; i < len; i++) {
char c = rest[i];
if (c == '(') {
level++;
} else if (c == ')') {
level--;
} else if (c == ' ' && level == 0) {
// 当括号层级为0时,空格是参数分隔符
strncpy(params[paramIndex], rest + start, i - start);
params[paramIndex][i - start] = '\0';
paramIndex++;
start = i + 1;
if (paramIndex == 2) {
break;
}
}
}
// 最后一个参数
if (paramIndex < 2) {
strcpy(params[paramIndex], rest + start);
}
}
// 去除字符串两端的空格
char* trim(char* str) {
// 去除开头空格
while (*str == ' ') str++;
// 去除结尾空格
int len = strlen(str);
while (len > 0 && str[len - 1] == ' ') {
str[--len] = '\0';
}
return str;
}
九、C++算法源码
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
// 函数声明
string calculate(const string& expr);
int evaluate(const string& expr);
vector<string> parseParams(const string& rest);
string trim(const string& str);
// 主函数
int main() {
string input;
getline(cin, input);
// 计算结果
string result = calculate(input);
cout << result << endl;
return 0;
}
// 主计算函数
string calculate(const string& expr) {
try {
int result = evaluate(expr);
return to_string(result);
} catch (...) {
return "error";
}
}
// 递归求值函数
int evaluate(const string& expr) {
string trimmedExpr = trim(expr);
// 如果是纯数字,直接返回
if (trimmedExpr[0] != '(') {
return stoi(trimmedExpr);
}
// 去掉外层括号
string inner = trimmedExpr.substr(1, trimmedExpr.length() - 2);
// 找到操作符
size_t firstSpace = inner.find(' ');
if (firstSpace == string::npos) {
throw runtime_error("无效表达式");
}
string op = inner.substr(0, firstSpace);
string rest = inner.substr(firstSpace + 1);
// 解析两个参数
vector<string> params = parseParams(rest);
int param1 = evaluate(params[0]);
int param2 = evaluate(params[1]);
// 根据操作符计算结果
if (op == "add") {
return param1 + param2;
} else if (op == "sub") {
return param1 - param2;
} else if (op == "mul") {
return param1 * param2;
} else if (op == "div") {
if (param2 == 0) {
throw runtime_error("除零错误");
}
return param1 / param2;
} else {
throw runtime_error("未知操作符");
}
}
// 解析参数,返回两个参数的向量
vector<string> parseParams(const string& rest) {
vector<string> params;
int level = 0;
size_t start = 0;
// 遍历字符串,根据括号层级分割参数
for (size_t i = 0; i < rest.length(); i++) {
char c = rest[i];
if (c == '(') {
level++;
} else if (c == ')') {
level--;
} else if (c == ' ' && level == 0) {
// 当括号层级为0时,空格是参数分隔符
params.push_back(rest.substr(start, i - start));
start = i + 1;
if (params.size() == 2) {
break;
}
}
}
// 最后一个参数
if (params.size() < 2) {
params.push_back(rest.substr(start));
}
return params;
}
// 去除字符串两端的空格
string trim(const string& str) {
size_t first = str.find_first_not_of(' ');
if (first == string::npos) {
return "";
}
size_t last = str.find_last_not_of(' ');
return str.substr(first, last - first + 1);
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2025 B卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。