【LeetCode-栈】逆波兰表达式求值

题目描述

根据 逆波兰表示法,求表达式的值。

有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:

  • 整数除法只保留整数部分。
  • 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

示例:

输入: ["2", "1", "+", "3", "*"]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

输入: ["4", "13", "5", "/", "+"]
输出: 6
解释: 该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6

输入: ["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 + 2 ) * ( 3 + 4 ) 。
  • 该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
  • 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
  • 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。

思路

题目对于逆波兰表达式的介绍很有用,特别是这一句适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。算法也就是这样做的:

  • 定义一个存储数字的栈:
    • 如果当前元素是数字,则入栈;
    • 如果当前元素是运算符,则出栈两个元素进行运算,将结果压入栈中;

代码如下:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        if(tokens.empty()) return 0;

        stack<int> nums;
        for(int i=0; i<tokens.size(); i++){
            if(tokens[i].size()>1) nums.push(stoi(tokens[i]));  // 长度大于 1,肯定是数字
            else{
                if(isdigit(tokens[i][0])) nums.push(stoi(tokens[i]));
                else{
                    int a = nums.top(); nums.pop();
                    int b = nums.top(); nums.pop();
                    if(tokens[i]=="+") nums.push(b+a);
                    else if(tokens[i]=="-") nums.push(b-a);  // 注意是 b-a,不是 a-b
                    else if(tokens[i]=="*") nums.push(b*a);
                    else if(tokens[i]=="/") nums.push(b/a);  // 注意是 b/a,不是 a/b
                }
            }
        }
        return nums.top(); 
    }
};

需要注意的是,第一个出栈的元素为 a,第二个出栈的元素为 b,当前运算符为 opr,则操作是 b opr a,不是 a opr b。

原文地址:https://www.cnblogs.com/flix/p/13301694.html