一、题目描述:
给你一个字符串数组
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
三、先决知识点:
- 逆波兰表达式,也称为后缀表达式,是一种算术表达式的表示方法,其中操作符位于操作数之后。
- string对象使用双引号包裹,和本题的运算符比较时,运算符也要使用双引号包裹才能比较。
- stoi函数可以将string字符串对象转换为整型int。
四、思路讲解:
- 建立一个stack栈,将所有非运算符的字符串,转换为整型,压栈。
- 遇到运算符,弹出两个栈顶元素,使用运算符运算后压栈。
- 要注意第一个出栈的元素是右操作数,第二个出栈的元素才是左操作数,不能搞反。
- 最后返回栈顶元素即可。
五、C++代码:
第一版 :
class Solution { public: int evalRPN(vector<string>& tokens) { stack<int> s;//建立一个栈 int tmp1=0;//设置两个整形变量,存储栈顶的两个元素 int tmp2=0; for(auto& a: tokens)//遍历vector { if(a!="+"&&a!="-"&&a!="*"&&a!="/")//非运算符,就压栈 { s.push(stoi(a)); } else//遇到运算符,出栈两个栈顶元素,运算后,将结果压栈 { tmp1=s.top(); s.pop(); tmp2=s.top(); s.pop(); if(a=="+") tmp2=tmp2+tmp1; else if(a=="-") tmp2=tmp2-tmp1; else if(a=="*") tmp2=tmp2*tmp1; else tmp2=tmp2/tmp1; s.push(tmp2); } } return s.top();//返回栈顶元素,栈顶元素就是算式最终结果 } };
第二版: 优化逻辑,代码更容易看懂
class Solution { public: int evalRPN(vector<string>& tokens) { stack<int> s;//建立一个栈 int right=0;//设置左右操作数 int left=0; for(auto a:tokens)//遍历 { if(a=="+"||a=="-"||a=="*"||a=="/")//如果为操作符 { right=s.top();//出栈右操作数 s.pop(); left=s.top();//出栈左操作数 s.pop(); switch(a[0])//a是string对象,a的[0]才是常量 { case '+': s.push(left+right); break; case '-': s.push(left-right); break; case '*': s.push(left*right); break; case '/': s.push(left/right); } } else//不是操作数,就转换为整型压栈 { s.push(stoi(a)); } } return s.top();//栈顶元素,就是算式的结果 } };