当前位置:网站首页>逆波兰表达式求值<难度系数>
逆波兰表达式求值<难度系数>
2022-06-28 07:23:00 【华为云】
题述:根据 逆波兰表示法,求表达式的值。有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。注意 两个整数之间的除法只保留整数部分。可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例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
提示:
- 1 <= tokens.length <= 10^4^
- tokens[i] 是一个算符("+"、"-"、"*" 或 “/”),或是在范围 [-200, 200] 内的一个整数
逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
中缀表达式面临的最大问题在于程序不方便运算,因为运算符优先级的问题,所以我们处理这种问题可以先将中缀表达式转换成后缀表达式,然后用后缀表达式进行运算。
大概了解下中缀表达式转后缀表达式,这里需要借助栈
该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
逆波兰表达式主要有以下两个优点:
- 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
- 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
🧷 平台:Visual studio 2017 && windows
核心思想:在了解完后缀表达式怎么由中缀表达式转换后,这里题目本意是需要我们计算后缀表达式的值。
🧿 版本一
class Solution {public: int evalRPN(vector<string>& tokens) { stack<int> st; for(const auto str : tokens) { //建议不要这样写,因为如果操作数是负数,就会出bug /*switch(str[0]) { case: '+': //... ... }*/ int left, right; //+、-、*、/,就出两个栈顶的元素,top1对应right,top2对应left,再把计算的结果入栈 if(str == "+") { right = st.top(); st.pop(); left = st.top(); st.pop(); st.push(left + right); } else if(str == "-") { right = st.top(); st.pop(); left = st.top(); st.pop(); st.push(left - right); } else if(str == "*") { right = st.top(); st.pop(); left = st.top(); st.pop(); st.push(left * right); } else if(str == "/") { right = st.top(); st.pop(); left = st.top(); st.pop(); st.push(left / right); } else//操作数 { //入栈前,将字符串转整型 st.push(stoi(str)); } } //返回此时栈顶的元素 return st.top(); }};🧿 版本二 (优化版本一)
优化的点在于 “ 在判断操作符时有大量冗余的代码 ”。
解决方案:
- 封装一个成员函数 (能解决,但还能更好的方法 ?)。
- 这道题使用 map 非常简单,但目前我们还没学,就不谈了。
- 使用逻辑或 “ || ”,这种写法的问题是把运算结果 push 时不知道是什么操作符。解决方法就是定义一个 48 大小的数组建立映射关系,比如在下标 47 的位置存储 “ / ”,然后根据对应的字符就可以取到对应的符号,但是数组里所存储的字符,不是类型,所以没错,~~ 翻车了,连第 2 种方案好像也翻车了,所以这里给成员函数好像是比较好的方案了,或者在 “ || ” 的基础上使用 switch 语句 (这两种方法差不多,只是减少了代码量,本质并没有多少的改进)。无妨,多翻车才能更好的上车嘛 !!!
注:其实也有更好的简化的方案的,只不过目前我们玩不了,这里先吊下大家的胃口 —— C++11 的包装器。也欢迎大家有更好的方案可以在评论区留言。

//版本二(优化版本一)class Solution {public: //解决方案一: void getnum(stack<int>& st, int& l, int& r) {} int evalRPN(vector<string>& tokens) { stack<int> st; for(const auto str : tokens) { int left, right; if(str == "+" || str == "-" || str == "*" || str == "/") { right = st.top(); st.pop(); left = st.top(); st.pop(); switch(str[0]) { case '+': st.push(left + right); break; case '-': st.push(left - right); break; case '*': st.push(left * right); break; case '/': st.push(left / right); break; } } else { st.push(stoi(str)); } } return st.top(); }};🧿 版本三 (优化版本二,骚操作)
这里可以先跳过,把后面 C++11 的包装器、map 等,等学了再来看。
class Solution {public: int evalRPN(vector<string>& tokens) { map<string, function<int(int, int)>> opCountMap = { {"+", [](int x, int y)->int{return x + y;}}, {"-", [](int x, int y)->int{return x - y;}}, {"*", [](int x, int y)->int{return x * y;}}, {"/", [](int x, int y)->int{return x / y;}} }; stack<int> st; for(auto& str : tokens) { if(str == "+" || str == "-" || str == "*" || str == "/") { int right = st.top(); st.pop(); int left = st.top(); st.pop(); st.push(opCountMap[str] (left, right)); } else { st.push(stoi(str)); } } return st.top(); }};边栏推荐
- Reading notes - MySQL technology l act: InnoDB storage engine (version 2)
- C语言教程大全
- Is it safe to open an account on Dongfang fortune
- 什么是EC鼓风机(ec blower fan)?
- Block transmission by golang gin framework
- HTTP Caching Protocol practice
- Wechat applets - basics takes you to understand the life cycle of applets (I)
- 卸载重装最新版mysql数据库亲测有效
- Detailed explanation of collection class methods____ (4) Judgment and assignment, etc
- MMR rearrangement (similarity is calculated by editing distance and repeatability)
猜你喜欢

kubernetes部署thanos ruler的发送重复告警的一个隐秘的坑
![[c #] [reprint]furion frame address and tutorial address](/img/b2/e1c30153c4237188b60e9523b0a5d8.png)
[c #] [reprint]furion frame address and tutorial address

kubelet垃圾(退出的容器和未使用的镜像)回收源码分析

小小一款代码编辑器竟然也可以有程序运行之功能——Sublime Text3运行各种语言程序的总结

kubernetes删除pod的流程的源码简析

Leetcode+ 66 - 70 high precision, two sub topics

Construction and exploration of vivo database and storage platform

Practice and exploration of vivo live broadcast application technology

Libuv framework echo server C source code explanation (TCP part)

SQL statement optimization steps (1)
随机推荐
NDK 交叉编译
Huawei cloud computing physical node cna installation tutorial
[ thanos源码分析系列 ]thanos query组件源码简析
7-1 懂的都懂
GoLand IDE and delve debug Go programs in kubernetes cluster
C language tutorial
Evolution of vivo push platform architecture
扩展Prometheus的解决方案thanos的简介和几个月使用心得
open62541直接导入NodeSet文件
Leetcode+ 66 - 70 high precision, two sub topics
R and RGL draw 3D knots
Dbeaver 22.1.1 release, visual database management platform
R 语言 ggmap 可视化集群
Recommend several 0 code, free, learning and using visualization tools
Design and practice of vivo sensitive word matching system
QT -- communication protocol
Block transmission by golang gin framework
Jetpack - defects of livedata component and Countermeasures
MySQL installation steps - Linux configuration file JDK installation (II)
kubernetes删除pod的流程的源码简析