每天学习一点算法 2026/04/16
逆波兰表达式求值
给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
有效的算符为 '+'、'-'、'*' 和 '/' 。
每个操作数(运算对象)都可以是一个整数或者另一个表达式。
两个整数之间的除法总是 向零截断 。
表达式中不含除零运算。
输入是一个根据逆波兰表示法表示的算术表达式。
答案及所有中间计算结果可以用 32 位 整数表示。
输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
根据这两示例我们可以看出符号的前两位就是参与计算的数字,那么我们就可以找出每一步计算的符号和参与计算的数字,用计算结果替换掉他们,直到没有符号,剩下的最后一位就是计算结果
typescript
function evalRPN(tokens: string[]): number {
while (tokens.length > 1) {
// 找到符号和参数计算的两个数字
const index = tokens.findIndex(item => item == '+' || item == '-' || item == '*' || item == '/')
const num1 = Number(tokens[index - 2])
const num2 = Number(tokens[index - 1])
// 根据符号计算结果,并替换掉这三个元素
switch (tokens[index]) {
case '+': {
tokens.splice(index - 2, 3, (num1 + num2).toString())
break
}
case '-': {
tokens.splice(index - 2, 3, (num1 - num2).toString())
break
}
case '*': {
tokens.splice(index - 2, 3, (num1 * num2).toString())
break
}
case '/': {
tokens.splice(index - 2, 3, Math.trunc(num1 / num2).toString())
break
}
}
}
return Number(tokens[0]) // 返回最后结果
};
我们还可以用空间换时间,维护一个栈,然后循环 tokens 所有元素,遇到数字就压栈,遇到符号就弹出两个参与计算的数字,再将计算结果压栈,遍历完所有的元素,最后栈里就是最终的计算结果
typescript
function evalRPN(tokens: string[]): number {
const stack: number[] = []
for (let i = 0; i < tokens.length; i++) {
switch (tokens[i]) {
case '+': {
const num2 = stack.pop()
const num1 = stack.pop()
stack.push(num1 + num2)
break
}
case '-': {
const num2 = stack.pop()
const num1 = stack.pop()
stack.push(num1 - num2)
break
}
case '*': {
const num2 = stack.pop()
const num1 = stack.pop()
stack.push(num1 * num2)
break
}
case '/': {
const num2 = stack.pop()
const num1 = stack.pop()
stack.push(Math.trunc(num1 / num2))
break
}
default: {
stack.push(Number(tokens[i]))
}
}
}
return stack.pop()
};
题目来源:力扣(LeetCode)