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] 题目描述 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除 ...
随机推荐
- spring 简单实现BeanFactory(转)
原文地址: http://blog.csdn.net/mlc1218559742/article/details/52776160 有没有发现上面的代码与利用反射实现工厂模式的代码很相似.对,你没有看 ...
- Hdu 4738 Caocao's Bridges (连通图+桥)
题目链接: Hdu 4738 Caocao's Bridges 题目描述: 有n个岛屿,m个桥,问是否可以去掉一个花费最小的桥,使得岛屿边的不连通? 解题思路: 去掉一个边使得岛屿不连通,那么去掉的这 ...
- 平方分割poj2104K-th Number
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 59798 Accepted: 20879 Ca ...
- Linux下磁盘分区、挂载、卸载操作记录
Linux下磁盘分区.挂载.卸载操作记录. 操作环境:CentOS release 6.5 (Final) Last :: from 118.230.194.76 [root@CentOS ~]# [ ...
- 232 Implement Queue using Stacks 用栈来实现队列
使用栈来实现队列的如下操作: push(x) -- 将一个元素放入队列的尾部.pop() -- 从队列首部移除元素.peek() -- 返回队列首部的元素.empty() -- 返回队列是否为空.注意 ...
- Debug技巧(1)
首先声明,以下有些是自己遇到的问题自己解决了,其它里面包括了网上看到的Debug经验和书里看到的经验,时间问题就不一一说明,如有侵权,私信我进行删除,我会道歉.我写这个的本意是记录我学习中遇到的问题, ...
- (转)版本管理工具介绍——SVN篇(一)
http://blog.csdn.net/yerenyuan_pku/article/details/72620101 SVN是何物 SVN是Subversion的简称,是一款集中式的开源版本控制系统 ...
- (转) 淘淘商城系列——使用SolrJ查询索引库
http://blog.csdn.net/yerenyuan_pku/article/details/72908538 我们有必要在工程中写查询索引库的代码前先进行必要的测试.我们先到Solr服务页面 ...
- C++写注册表
1. 注册表简介 注册表是为Windows NT和Windows95中所有32位硬件/驱动和32位应用程序设计的数据文件,用于存储系统和应用程序的设置信息.16位驱动在Winnt (Win ...
- offset 后 指针数组转换
AcDbObjectId pidoffset; AcDbPolyline *plineOffset; AcDbVoidPtrArray ptarr=NULL; pline->getOffsetC ...