Medium
题目描述
给你一个字符串数组 tokens ,表示一个根据逆波兰表示法表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'、'-'、'*'和'/'。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式的结果。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
示例 1:
输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:
输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:
输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
输出:22
解释:该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
提示:
1 <= tokens.length <= 10^4tokens[i]是一个算符("+"、"-"、"*"或"/"),或是在范围[-200, 200]内的一个整数
解题思路
解题思路
逆波兰表达式(后缀表达式)的特点是操作符在操作数之后,这种形式天然适合用栈来处理。
核心思想:
- 遍历表达式中的每个元素
- 如果是数字,直接入栈
- 如果是操作符,从栈中弹出两个操作数进行运算,将结果重新入栈
- 最终栈中只剩一个元素,即为最终结果
处理细节:
- 注意操作数的顺序:先弹出的是右操作数,后弹出的是左操作数
- 除法需要向零截断,可以用
int(a/b)实现 - 负数的处理:注意区分负号和减法操作符
算法步骤:
- 初始化一个栈
- 遍历 tokens 数组
- 判断当前元素是数字还是操作符
- 数字直接入栈,操作符取出栈顶两元素计算后入栈
- 返回栈顶元素
这是一个经典的栈应用问题,时间复杂度为 O(n),空间复杂度为 O(n)。
代码实现
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> stk;
for (const string& token : tokens) {
if (token == "+") {
int b = stk.top(); stk.pop();
int a = stk.top(); stk.pop();
stk.push(a + b);
} else if (token == "-") {
int b = stk.top(); stk.pop();
int a = stk.top(); stk.pop();
stk.push(a - b);
} else if (token == "*") {
int b = stk.top(); stk.pop();
int a = stk.top(); stk.pop();
stk.push(a * b);
} else if (token == "/") {
int b = stk.top(); stk.pop();
int a = stk.top(); stk.pop();
stk.push(a / b);
} else {
stk.push(stoi(token));
}
}
return stk.top();
}
};
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack = []
for token in tokens:
if token in "+-*/":
b = stack.pop()
a = stack.pop()
if token == '+':
stack.append(a + b)
elif token == '-':
stack.append(a - b)
elif token == '*':
stack.append(a * b)
else: # token == '/'
# 向零截断
stack.append(int(a / b))
else:
stack.append(int(token))
return stack[0]
public class Solution {
public int EvalRPN(string[] tokens) {
Stack<int> stack = new Stack<int>();
foreach (string token in tokens) {
if (token == "+") {
int b = stack.Pop();
int a = stack.Pop();
stack.Push(a + b);
} else if (token == "-") {
int b = stack.Pop();
int a = stack.Pop();
stack.Push(a - b);
} else if (token == "*") {
int b = stack.Pop();
int a = stack.Pop();
stack.Push(a * b);
} else if (token == "/") {
int b = stack.Pop();
int a = stack.Pop();
stack.Push(a / b);
} else {
stack.Push(int.Parse(token));
}
}
return stack.Peek();
}
}
var evalRPN = function(tokens) {
const stack = [];
const operators = new Set(['+', '-', '*', '/']);
for (let token of tokens) {
if (operators.has(token)) {
const b = stack.pop();
const a = stack.pop();
if (token === '+') {
stack.push(a + b);
} else if (token === '-') {
stack.push(a - b);
} else if (token === '*') {
stack.push(a * b);
} else if (token === '/') {
stack.push(Math.trunc(a / b));
}
} else {
stack.push(parseInt(token));
}
}
return stack[0];
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历所有token,每次操作都是O(1) |
| 空间复杂度 | O(n) | 栈的空间消耗,最坏情况下存储所有数字 |
相关题目
. Basic Calculator (Hard)
. Expression Add Operators (Hard)