leetcode算法学习----逆波兰表达式求值(后缀表达式)
下面题目是LeetCode算法:逆波兰表达式求值(java实现)
逆波兰表达式即后缀表达式。
题目:
有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式、同时支持括号。(假设所有的数字均为整数,不考虑精度问题)
计算工具:
/**
* 计算工具
* @author monkjavaer
* @date 2018/9/13 14:35
*/
public class CalculatorUtil {
/**
* 加
*/
private static final String ADD = "+";
/**
* 减
*/
private static final String SUBTRACT = "-";
/**
* 乘
*/
private static final String MULTIPLICATION = "*";
/**
* 除
*/
private static final String DIVISION = "/";
/**
* 左括号
*/
private static final String LEFT_PARENTHESIS = "(";
/**
* 右括号
*/
private static final String RIGHT_PARENTHESIS = ")"; /**
*
* 提供给外部的计算方法
*
* @param expression 后缀表达式
* @return 计算结果
*/
public static int calculation(Expression expression) throws Exception {
List<String> list = getPostfix(expression);
Stack<Integer> calculationStack = new Stack<>();
Integer operandRight;
Integer operandLeft;
for (String item : list) {
if (ADD.equals(item)) {
operandRight = calculationStack.pop();
operandLeft = calculationStack.pop();
calculationStack.push(operandLeft + operandRight);
} else if (SUBTRACT.equals(item)) {
operandRight = calculationStack.pop();
operandLeft = calculationStack.pop();
calculationStack.push(operandLeft - operandRight);
} else if (MULTIPLICATION.equals(item)) {
operandRight = calculationStack.pop();
operandLeft = calculationStack.pop();
calculationStack.push(operandLeft * operandRight);
} else if (DIVISION.equals(item)) {
operandRight = calculationStack.pop();
operandLeft = calculationStack.pop();
calculationStack.push(operandLeft / operandRight);
} else {
calculationStack.push(Integer.parseInt(item));
}
} return calculationStack.pop();
} /**
* 判断字符为运算符(+,-,*,/)
*
* @param c 输入字符
* @return
*/
private static boolean isOperator(char c) { return ADD.equals(String.valueOf(c)) || SUBTRACT.equals(String.valueOf(c)) ||
MULTIPLICATION.equals(String.valueOf(c)) || DIVISION.equals(String.valueOf(c));
} /**
* 返回的是运算符的优先级
*
* @param operator
* @return
*/
private static int priority(Operator operator) {
char operatorName = operator.getOperatorName();
if (ADD.equals(String.valueOf(operatorName)) || SUBTRACT.equals(String.valueOf(operatorName))) {
return 1;
} else if (MULTIPLICATION.equals(String.valueOf(operatorName)) || DIVISION.equals(String.valueOf(operatorName))) {
return 2;
} else {
return 0;
}
} /**
* 通过表达式获得后缀表达式
*
* @param expression
* @return
*/
private static List<String> getPostfix(Expression expression) throws Exception {
/**
* 操作符栈
*/
Stack<Operator> operatorStack = new Stack<>(); /**
* 存放后缀表达式
*/
List<String> operandList = new ArrayList<>(); String expressionStr = expression.getExpressionStr();
for (int i = 0; i < expressionStr.length(); i++) {
char oneChar = expressionStr.charAt(i); Operator operator = new Operator();
operator.setOperatorName(oneChar); //遇到操作数:直接输出(添加到后缀表达式中)
if (Character.isDigit(oneChar)) {
int num = oneChar - '0';
while (i + 1 < expressionStr.length() && Character.isDigit(expressionStr.charAt(i + 1))) {
num = num * 10 + expressionStr.charAt(i + 1) - '0';
i++;
}
operandList.add(String.valueOf(num));
} else if (LEFT_PARENTHESIS.equals(String.valueOf(oneChar))) {
//遇到左括号:将其入栈
operatorStack.push(operator);
} else if (RIGHT_PARENTHESIS.equals(String.valueOf(oneChar))) {
//遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
while (!LEFT_PARENTHESIS.equals(String.valueOf(operatorStack.peek().getOperatorName()))) {
operandList.add(String.valueOf(operatorStack.pop().getOperatorName()));
}
//然后弹出左括号
operatorStack.pop();
} else if (isOperator(oneChar)) {
//遇到运算符
//栈为空时,直接入栈
if (operatorStack.isEmpty()) {
operatorStack.push(operator);
} else {
// 如果读入的操作符为非")"且优先级比栈顶元素的优先级高或一样
if (priority(operatorStack.peek()) < priority(operator)) {
operatorStack.push(operator);
} else if (priority(operatorStack.peek()) >= priority(operator)) {
operandList.add(String.valueOf(operatorStack.pop().getOperatorName()));
operatorStack.push(operator);
}
}
}
} //最终将栈中的元素依次出栈。
while (!operatorStack.isEmpty()) {
operandList.add(String.valueOf(operatorStack.pop().getOperatorName()));
}
System.out.println(operandList);
return operandList;
} }
表达式:
/**
* 表达式
*
* @author monkjavaer
* @date 2018/9/12 19:42
*/
public class Expression { /**
* 表达式名字
*/
private String name; /**
* 表达式
*/
private String expressionStr; /**
* 表达式值
*/
private int value; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getExpressionStr() {
return expressionStr;
} public void setExpressionStr(String expressionStr) {
this.expressionStr = expressionStr;
} public int getValue() {
return value;
} public void setValue(int value) {
this.value = value;
} }
操作数:
/**
* 操作数
* @author monkjavaer
* @date 2018/9/12 19:43
*/
public class Operand {
/**
* 操作数值
*/
private Integer operandValue; public Integer getOperandValue() {
return operandValue;
} public void setOperandValue(Integer operandValue) {
this.operandValue = operandValue;
}
}
运算符:
/**
* 运算符
*
* @author monkjavaer
* @date 2018/9/12 19:43
*/
public class Operator {
/**
* 运算符符号
*/
private char operatorName; public char getOperatorName() {
return operatorName;
} public void setOperatorName(char operatorName) {
this.operatorName = operatorName;
} }
测试:
/**
* @author monkjavaer
* @date 2018/9/13 11:49
*/
public class Test { public static void main(String[] args) {
Expression expression = new Expression();
expression.setExpressionStr("4 +(13 - 5)");
try {
System.out.println(CalculatorUtil.calculation(expression));
} catch (Exception e) {
e.printStackTrace();
}
} }
leetcode算法学习----逆波兰表达式求值(后缀表达式)的更多相关文章
- NYOJ 35 表达式求值(逆波兰式求值)
http://acm.nyist.net/JudgeOnline/problemset.php?typeid=4 NYOJ 35 表达式求值(逆波兰式求值) 逆波兰式式也称后缀表达式. 一般的表达式求 ...
- 中缀表达式变后缀表达式、后缀表达式(逆波兰)求值(python版本)
定义: 中缀表达式: 在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表达式 后缀表达式: 又叫逆波兰表达式 ,不包含括号,运算符放在两个运算对象的后面,所有的计算 ...
- TOJ1302: 简单计算器 && TOJ 4873: 表达式求值&&TOJ3231: 表达式求值
这些都是应用Python的eval函数的一些题目! TOJ1302传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=show ...
- C++基础算法学习——逆波兰表达式问题
例题:逆波兰表达式逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3.逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 ...
- ACM-ICPC 2018 沈阳赛区网络预赛 B Call of Accepted(表达式求值)
题目链接:https://nanti.jisuanke.com/t/31443 相关前置链接 https://www.cnblogs.com/dolphin0520/p/3708602.html ht ...
- 【足迹C++primer】表达式求值
表达式求值 /** * 功能:表达式求值(0到9) * 时间:2014年6月15日08:02:31 * 作者:cutter_point */ #include<stdlib.h> #inc ...
- java实现算术表达式求值
需要根据配置的表达式(例如:5+12*(3+5)/7.0)计算出相应的结果,因此使用java中的栈利用后缀表达式的方式实现该工具类. 后缀表达式就是将操作符放在操作数的后面展示的方式,例如:3+2 后 ...
- LeetCode 150. 逆波兰表达式求值(Evaluate Reverse Polish Notation) 24
150. 逆波兰表达式求值 150. Evaluate Reverse Polish Notation 题目描述 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, /.每个运算对象 ...
- LeetCode:逆波兰表达式求值【150】
LeetCode:逆波兰表达式求值[150] 题目描述 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除 ...
随机推荐
- Notepad++安装插件
https://sourceforge.net/projects/npp-plugins/files/ 下载完插件后,通过notepad++的设置>>>>导入>>& ...
- 洛谷P3383 【模板】线性筛素数 (埃拉托斯特尼筛法)
题目描述 如题,给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内) 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示查询的范围和查询的个数. 接下来M行每行 ...
- 数据据操作 tp5
数据库操作-DB类 学习手册 数据库配置 注意1:在TP里面,可以在模块下面单独的建立一个database.php配置文件,代表这个模块就使用配置的这个数据库 注意2:我们可以在config.php里 ...
- HDU 1879(最小生成树)
#include "iostream" #include "algorithm" #include "cstdio" using names ...
- nodejs安装node-rsa遇到的问题及解决
nodejs第一次使用,故碰到一些小白问题: 1.使用 npm install node-rsa -S 2.封装rsa import NodeRSA from 'node-rsa'; const rs ...
- Spring:(三) --常见数据源及声明式事务配置
Spring自带了一组数据访问框架,集成了多种数据访问技术.无论我们是直接通过 JDBC 还是像Hibernate或Mybatis那样的框架实现数据持久化,Spring都可以为我们消除持久化代码中那些 ...
- [ CERC 2014 ] Vocabulary
\(\\\) \(Description\) 给出三个长度分别为 \(lenA,lenB,lenC\) 的三个字符串 \(A,B,C\) ,其中字符集只包括所有小写字母以及 \(?\) 号. 现在将所 ...
- C/c++中 数组全局变量的定义声明 与 引用声明
数组声明一次,所有的 定义声明 有切仅有一次! 别人遇到的问题如下: 在声明定义时,定义数组如下: int G_glob[100]; 在其他文件引用时声明如下: int *G_glob; 这样的操 ...
- Qt 5.8.3 部署/添加 Crypto++第三方库(5.6.5版本)
首先,Qt没有封装加解密算法库(其实有个哈希函数的函数).介于OpenSSL函数封装不友好,以及先前爆发的心脏滴血漏洞广受诟病,我们考虑在C++上使用一种新的,并且封装友好的,OOAD程度更高的加解密 ...
- codeforces_302D
D. Yaroslav and Time time limit per test 2 seconds memory limit per test 256 megabytes input standar ...