大家好,我是小魔龙,Unity3D软件工程师,VR、AR,虚拟仿真方向,不定时更新软件开发技巧,生活感悟,觉得有用记得一键三连哦。
一、题目
1、算法题目
“根据逆波兰表达式求表达式的值。”
2、题目描述
根据 逆波兰表示法,求表达式的值。
有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
注意 两个整数之间的除法只保留整数部分。
可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1: 输入: tokens = ["2","1","+","3","*"] 输出: 9 解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2: 输入: tokens = ["4","13","5","/","+"] 输出: 6 解释: 该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
二、解题
1、思路分析
首先来了解一下什么是逆波兰表达式。
逆波兰表达式是波兰的逻辑学家卢卡西维兹提出,逆波兰表达式的特点是:没有括号,运算符总是放在和它相关的操作数之后,所以,逆波兰表达式也被称为后缀表达式。
根据 逆波兰表示法,求表达式的值,可以使用栈存储操作数,从左到右遍历逆波兰表达式:
- 遇到操作数,将操作数入栈
- 遇到运算符,将两个操作数出栈,先出栈的右操作数,后出栈的是左操作数,使用运算符对两个操作数进行运算
- 将运算后的得到的新操作数入栈
整个逆波兰表达式遍历之后,栈内只有一个元素,也就是逆波兰表达式的值。
2、代码实现
代码参考:
class Solution { public int evalRPN(String[] tokens) { Deque<Integer> stack = new LinkedList<Integer>(); int n = tokens.length; for (int i = 0; i < n; i++) { String token = tokens[i]; if (isNumber(token)) { stack.push(Integer.parseInt(token)); } else { int num2 = stack.pop(); int num1 = stack.pop(); switch (token) { case "+": stack.push(num1 + num2); break; case "-": stack.push(num1 - num2); break; case "*": stack.push(num1 * num2); break; case "/": stack.push(num1 / num2); break; default: } } } return stack.pop(); } public boolean isNumber(String token) { return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token)); } }
3、时间复杂度
时间复杂度:O(n)
其中n是数组tokens的长度,需要遍历数组一次。
空间复杂度:O(n)
其中n是数组tokens的长度,栈内元素个数不会超过逆波兰表达式的长度。
三、总结
对于这道题来说,还可以使用递归来解。
因为对于逆波兰表达式来说,序列的最后一个符号一定是最先得到计算的,而一旦有符号,就至少需要两个以上的操作数。
用一个变量,记录表达式遍历的位置,遇到操作数可以返回,遇到符号则再递归地计算两个操作数,然后根据不同的符号进行对应的计算返回即可。