150.逆波兰表达式求值
练习次数 *
https://leetcode.cn/problems/evaluate-reverse-polish-notation/
- 逆波兰表达式求值 中等 │ 936 │ 55.0% 的 732.8K
给你一个字符串数组 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^4
- tokens[i] 是一个算符("+"、"-"、"*" 或 “/"),或是在范围 [-200, 200] 内的一个整数
逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
-
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
- 该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
逆波兰表达式主要有以下两个优点:
-
去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
- 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
// @leet start
func evalRPN(tokens []string) int {
s := NewStack()
for _, v := range tokens {
vs := v
if isOperate(vs) {
pop2 := s.Pop2()
if len(pop2) == 2 {
s.Push(operate(vs, pop2))
}
} else {
s.Push(vs)
}
}
if len(s.tokens) == 1 {
v, _ := strconv.Atoi(s.tokens[0])
return v
}
return 0
}
func operate(x string, oprand []string) string {
oprandInts := []int{}
for _, v := range oprand {
vv, _ := strconv.Atoi(v)
oprandInts = append(oprandInts, vv)
}
val := math.MaxInt
switch x {
case "+":
val = oprandInts[0] + oprandInts[1]
break
case "-":
val = oprandInts[0] - oprandInts[1]
break
case "*":
val = oprandInts[0] * oprandInts[1]
break
case "/":
val = oprandInts[0] / oprandInts[1]
break
}
return fmt.Sprintf("%d", val)
}
func isOperate(x string) bool {
// * 有效的算符为 '+'、'-'、'*' 和 '/' 。
for _, v := range []string{"+", "-", "*", "/"} {
if v == x {
return true
}
}
return false
}
type Stack struct {
tokens []string
}
func NewStack() Stack {
return Stack{}
}
func (s *Stack) Push(x string) {
s.tokens = append(s.tokens, x)
}
func (s *Stack) Pop2() []string {
if len(s.tokens) < 2 {
return nil
}
x := s.tokens[len(s.tokens)-2:]
s.tokens = s.tokens[:len(s.tokens)-2]
return x
}
// @leet end