题目描述
给你一个字符串数组 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 <= 104
tokens[i]
是一个算符("+"
、"-"
、"*"
或 "/"
),或是在范围 [-200, 200]
内的一个整数
逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
- 平常使用的算式则是一种中缀表达式,如
( 1 + 2 ) * ( 3 + 4 )
。
- 该算式的逆波兰表达式写法为
( ( 1 2 + ) ( 3 4 + ) * )
。
逆波兰表达式主要有以下两个优点:
- 去掉括号后表达式无歧义,上式即便写成
1 2 + 3 4 + *
也可以依据次序计算出正确结果。
- 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
解法
方法一
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | import operator
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
opt = {
"+": operator.add,
"-": operator.sub,
"*": operator.mul,
"/": operator.truediv,
}
s = []
for token in tokens:
if token in opt:
s.append(int(opt[token](s.pop(-2), s.pop(-1))))
else:
s.append(int(token))
return s[0]
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 | class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> stk = new ArrayDeque<>();
for (String t : tokens) {
if (t.length() > 1 || Character.isDigit(t.charAt(0))) {
stk.push(Integer.parseInt(t));
} else {
int y = stk.pop();
int x = stk.pop();
switch (t) {
case "+":
stk.push(x + y);
break;
case "-":
stk.push(x - y);
break;
case "*":
stk.push(x * y);
break;
default:
stk.push(x / y);
break;
}
}
}
return stk.pop();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> stk;
for (auto& t : tokens) {
if (t.size() > 1 || isdigit(t[0])) {
stk.push(stoi(t));
} else {
int y = stk.top();
stk.pop();
int x = stk.top();
stk.pop();
if (t[0] == '+')
stk.push(x + y);
else if (t[0] == '-')
stk.push(x - y);
else if (t[0] == '*')
stk.push(x * y);
else
stk.push(x / y);
}
}
return stk.top();
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | func evalRPN(tokens []string) int {
// https://github.com/emirpasic/gods#arraystack
stk := arraystack.New()
for _, token := range tokens {
if len(token) > 1 || token[0] >= '0' && token[0] <= '9' {
num, _ := strconv.Atoi(token)
stk.Push(num)
} else {
y := popInt(stk)
x := popInt(stk)
switch token {
case "+":
stk.Push(x + y)
case "-":
stk.Push(x - y)
case "*":
stk.Push(x * y)
default:
stk.Push(x / y)
}
}
}
return popInt(stk)
}
func popInt(stack *arraystack.Stack) int {
v, _ := stack.Pop()
return v.(int)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | function evalRPN(tokens: string[]): number {
const stack = [];
for (const token of tokens) {
if (/\d/.test(token)) {
stack.push(Number(token));
} else {
const a = stack.pop();
const b = stack.pop();
switch (token) {
case '+':
stack.push(b + a);
break;
case '-':
stack.push(b - a);
break;
case '*':
stack.push(b * a);
break;
case '/':
stack.push(~~(b / a));
break;
}
}
}
return stack[0];
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | impl Solution {
pub fn eval_rpn(tokens: Vec<String>) -> i32 {
let mut stack = vec![];
for token in tokens {
match token.parse() {
Ok(num) => stack.push(num),
Err(_) => {
let a = stack.pop().unwrap();
let b = stack.pop().unwrap();
stack.push(match token.as_str() {
"+" => b + a,
"-" => b - a,
"*" => b * a,
"/" => b / a,
_ => 0,
});
}
}
}
stack[0]
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | using System.Collections.Generic;
public class Solution {
public int EvalRPN(string[] tokens) {
var stack = new Stack<int>();
foreach (var token in tokens)
{
switch (token)
{
case "+":
stack.Push(stack.Pop() + stack.Pop());
break;
case "-":
stack.Push(-stack.Pop() + stack.Pop());
break;
case "*":
stack.Push(stack.Pop() * stack.Pop());
break;
case "/":
var right = stack.Pop();
stack.Push(stack.Pop() / right);
break;
default:
stack.Push(int.Parse(token));
break;
}
}
return stack.Pop();
}
}
|
方法二