栈与队列(六)

leetcode150. 逆波兰表达式求值

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

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

说明:

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

示例
逆波兰表达式:

逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。

  • 平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
  • 该算式的逆波兰表达式写法为 ( ( 1 2 + )( 3 4 + ) * ) 。

逆波兰表达式主要有以下两个优点

  • 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
  • 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。

思路

看一下本题,「其实逆波兰表达式相当于是二叉树中的后序遍历」。可以把运算符作为中间节点,按照后序遍历的规则画出一个二叉树。

例: 2 + 4 的波兰表达式为 24+, 形象为二叉树如图:
1
得到的后序24+, 就是波兰表达式.

但我们没有必要从二叉树的角度去解决这个问题,只要知道逆波兰表达式是用后续遍历的方式把二叉树序列化了,就可以了。

在进一步看,本题中每一个子表达式要得出一个结果,然后拿这个结果再进行运算,那么栈与队列:匹配问题都是栈的强项非常像了.

运算动画如下:
动画演示
这和1047. 删除字符串中的所有相邻重复项是差不多的,只不过本题不要相邻元素做消除了,而是做运算

C++代码

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;  //注意存储int型变量, 我们只将数值入栈, 遇到运算符就取栈顶元素进行运算
        for (int i = 0; i < tokens.size(); i++)
        {
            if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/")
            {
                //遇到运算符取栈顶元素
                int num1 = st.top();    //注意num1是运算符右边的数
                st.pop();
                int num2 = st.top();    //num2是运算符左边的数
                st.pop();
                //将运算结果重新入栈
                if (tokens[i] == "+") st.push(num2 + num1);
                else if (tokens[i] == "-") st.push(num2 - num1);
                else if (tokens[i] == "*") st.push(num2 * num1);
                else if (tokens[i] == "/") st.push(num2 / num1);    //因为提莫说明了表达式总会得出有效数值且不存在除数为 0 的情况。因此这里不考虑num1为0的情况.
            }
            else
            {
                //当前遍历字符为数值,直接入栈
                st.push(stoi(tokens[i]));   //stoi 将字符串转换成10进制的int
            }
        }
        int result = st.top();
        st.pop();
        return result;
    }
};

Carl的题外话

我们习惯看到的表达式都是中缀表达式,因为符合我们的习惯,但是中缀表达式对于计算机来说就不是很友好了。

例如:4 + 13 / 5,这就是中缀表达式,计算机从左到右去扫描的话,扫到13,还要判断13后面是什么运算法,还要比较一下优先级,然后13还和后面的5做运算,做完运算之后,还要向前回退到 4 的位置,继续做加法,你说麻不麻烦!

那么将中缀表达式,转化为后缀表达式之后:[“4”, “13”, “5”, “/”, “+”] ,就不一样了,计算机可以利用栈里顺序处理,不需要考虑优先级了。也不用回退了, 「所以后缀表达式对计算机来说是非常友好的。」

可以说本题不仅仅是一道好题,也展现出计算机的思考方式。

原文:https://github.com/youngyangyang04/leetcode-master/blob/master/problems/0150.%E9%80%86%E6%B3%A2%E5%85%B0%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%B1%82%E5%80%BC.md

Carl哥的公众号:代码随想录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值