剑指 Offer II 036. 后缀表达式(栈模块)

123 阅读2分钟

每日刷题第16天 2021.1.11

后缀表达式

  • 难度:中等
  • 方法:栈

题目

  • 根据 逆波兰表示法,求该后缀表达式的计算结果。
  • 有效的算符包括 +-*/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

示例

输入: tokens = ["2","1","+","3","*"]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
输入: tokens = ["4","13","5","/","+"]
输出: 6
解释: 该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
输入: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 + * 也可以依据次序计算出正确结果。
    • 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。

解法

  • 使用数组模拟栈。
  • 遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。
/**
* @param {string[]} tokens
* @return {number}
*/
var evalRPN = function(tokens) {
// 模拟栈
// 数字:压入栈,运算符:弹出两个数进行运算,结果再塞入栈中
let stack = [];
// 两个数字
let a,b,ans;
for (let i = 0;i < tokens.length; i++) {
// 字符,需要弹出两个数字进行计算
if (tokens[i] == '+' || tokens[i] == '-' || tokens[i] == '*' || tokens[i] == '/') {
  a = stack.pop();
  b = stack.pop();
  // console.log('char a,b',a,b,'i',tokens[i]);
  if (tokens[i] == '+') {
    ans = a + b;
  }else if (tokens[i] == '-') {
    ans = b - a;
  }else if (tokens[i] == '*') {
    ans = a * b;
  }else if (tokens[i] == '/') {
  // 除法只保留 整数
    ans = parseInt(b / a);
  }
  stack.push(ans);
  // console.log('计算后的',stack);
}else {
  // 数字
  stack.push(parseInt(tokens[i]));
}
}
// 最后栈中还存在一个数,就是结果
// console.log('stack', stack);
return stack;
};

附录

  • 需要⚠️注意:字符串数组中的每一项,取出来是字符串类型的,两数相加会出错
    • '1' + '2' = '12'
    • 1 + 2 = 3使用parseInt函数将字符串转换成数字,再进行计算。
  • 需要注意⚠️:除法 和 减法 除数和被除数是不能调换位置的,否则结果会出错。
    • 因此后pop出来的,作为除数
    • pop出来的,作为被除数