力扣oj链接:https://leetcode.cn/problems/evaluate-reverse-polish-notation/
一、逆波兰表示法
百科解释:逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种是由波兰数学家扬·武卡谢维奇1920年引入的数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法。
中缀表达式:就是我们平时用的表达式,比如 1+((2+3)*4)-5这种表达式
后缀表达式(逆波兰式):就是通过逆波兰表示法将中缀表达式进行转换,将所有操作符置于操作数的后面,操作数就是数字,操作符就是+、-、*、/这一类运算符
比如:“1+((2+3)*4)-5”转换为后缀表达式是”1 2 3 + 4 * + 5 -”,可以发现后缀表达式里没有括号。
具体可以用这样的方法转换:
这里我们先把中缀表达式写为这样:((1+((2 + 3)*4))-5)在表达式里每一步运算都加上括号,颜色相同的括号相对应,然后我们将对应的操作符(运算符)挪到对应的括号后面,如下:
((1((2 3)+4)*)+5)-
然后我们去掉括号就得到了后缀表达式:1 2 3 + 4 * + 5 -
二、解题思路
这个题目题意,就是将后缀表达式放进数组里,然后对这个数组进行遍历,然后一个一个的放进栈中运行,具体思路如下:
首先将表达式中的数字依次放入栈中,逢操作符就停止入栈,然后将栈顶的数字作为遇到的操作符
右边的操作数,栈顶下的数字作为操作符左边的操作数,因为操作符的不同左右不可颠倒,出栈以后对出栈后形成的表达式进行运算后,将此结果入栈,然后将原表达式继续入栈。同理进行,最后结果应为16。
图示如下:
具体代码编写如下:
1.首先我们定义一个evalRPN()方法,参数为tokens数组,数组中存放你想要输入的后缀表达式,如题https://leetcode.cn/problems/evaluate-reverse-polish-notation/中所示,然后定义一个栈:
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>(); //先定义一个栈
}
2.然后我们需要遍历这个数组,将数组元素放入到栈中
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>(); //先定义一个栈
for (String x: tokens) { //使用foreach遍历
}
}
在遍历数组过程中,我们需要判断遍历的元素是否为操作符,因为操作符不放入栈中,所以我们需要定义一个方法,判断遍历的元素是不是操作符:
//判断evalRPN()方法中,foreach遍历的元素是不是运算符
private boolean isOperation(String x) {
if(x.equals("+") || x.equals("-") || x.equals("*") || x.equals("/")) {
return true;
}
return false;
}
3.根据遍历进栈时是否为位操作符确定条件
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>(); //先定义一个栈
for (String x: tokens) { //遍历输入的数组(由后缀表达式组成)
if (!isOperation(x)) {//如果不是操作符,直接入栈
stack.push(Integer.parseInt(x));//因为x是string类型,不能push到栈中没所以需要转换
} else {//如果不是操作符
//定义遍历进栈时遇到操作符后出栈的操作数num2,num1,num2为操作符右边的操作数
int num2 = stack.pop();
int num1 = stack.pop();
switch (x) { //根据操作符的不同去定义后续入栈的几种可能
case "+" :
stack.push(num1+num2);
break;
case "-" :
stack.push(num1-num2);
break;
case "*" :
stack.push(num1*num2);
break;
case "/" :
stack.push(num1/num2);
break;
}
}
}
return stack.pop();
}