日野弥生:勉強しよう
LeetCode 150 - 逆波兰表达式求值
发表于2025年02月12日
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。 平常使用的算式则是一种中缀表达式,如: $(1+2)*(3+4)$
该算式的逆波兰表达式写法为: $((12+)(34+)*)$
逆波兰表达式主要有以下两个优点: 1、去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。 2、适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> stk;
for (int i = 0; i < tokens.size(); i++)
{
/* 这里也可以使用char类型,且用std::isdigit(),但是leetcode系统不支持,原因不明 */
string& token = tokens[i];
/* 考虑到有负数的情况,所以还是直接排除掉四则运算最简单直接 */
if (!isOperator(token))
/* 注意利用std::atoi对字符串转换 */
stk.push(atoi(token.c_str()));
else
{
int num2 = stk.top();
stk.pop();
int num1 = stk.top();
stk.pop();
/* 不能写成token */
switch (token[0]) {
case '+':
stk.push(num1 + num2);
break;
case '-':
stk.push(num1 - num2);
break;
case '*':
stk.push(num1 * num2);
break;
case '/':
stk.push(num1 / num2);
break;
}
}
}
/* 循环结束后的栈顶的元素就是结果 */
return stk.top();
}
bool isOperator(const string& token) {
return (token == "+" || token == "-" || token == "*" || token == "/");
}
};
用python3实现时,可以利用operator库和finally机制
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
# 利用字典存储运算符,operator库里的函数
op_to_binary_fn = {
"+": operator.add,
"-": operator.sub,
"*": operator.mul,
# 注意不能调用地板除法,得利用向下取整的除法,这里用lambda实现
"/": lambda x, y: int(x / y),
}
stack = list()
for token in tokens:
# 利用抛异常和finally关键字实现字符串到数字的转换,C++没有finally是真难受
try:
num = int(token)
except ValueError:
num2 = stack.pop()
num1 = stack.pop()
num = op_to_binary_fn[token](num1, num2)
finally:
stack.append(num)
return stack[0]