每日刷题第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出来的,作为被除数
- 因此后