逆波兰表达式求值(150. 逆波兰表达式求值&&剑指 Offer II 036. 后缀表达式)
题目:
逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
- 平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
- 该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
逆波兰表达式主要有以下两个优点:
- 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
- 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
思路:
【1】这道题本身就是比较简单的,根据波兰表达式的定义其实借助辅助空间更容易理解,而且时间复杂度和空间复杂度都为O(N)
【2】基于此其实还可以进一步优化就是将空间复杂度降低为O(1),需要两个指针和两个存储变量,然后在本身的数组上变动。
代码展示:
//常规做法 //执行用时:7 ms, 在所有 Java 提交中击败了20.65%的用户 //内存消耗:41.1 MB, 在所有 Java 提交中击败了55.71%的用户 class Solution { public int evalRPN(String[] tokens) { if (tokens.length == 1 ){ return Integer.parseInt(tokens[0]); } Stack<Integer> stack = new Stack<>(); int a,b; for (int i = 0; i<tokens.length;i++){ if (!"+".equals(tokens[i]) && !"-".equals(tokens[i]) && !"*".equals(tokens[i]) && !"/".equals(tokens[i])){ stack.add(Integer.parseInt(tokens[i])); }else { b = Objects.requireNonNull(stack.pop()); a = Objects.requireNonNull(stack.pop()); switch (tokens[i]){ case "+": stack.add(a+b); break; case "-": stack.add(a-b); break; case "*": stack.add(a*b); break; case "/": stack.add(a/b); break; default: break; } } } return stack.pop(); } } //用数组替换栈数据结构的做法 //执行用时:4 ms, 在所有 Java 提交中击败了96.23%的用户 //内存消耗:41.2 MB, 在所有 Java 提交中击败了42.76%的用户 class Solution { public int evalRPN(String[] tokens) { if (tokens.length == 1 ){ return Integer.parseInt(tokens[0]); } int[] stack = new int[tokens.length]; int a,b,index = 0; for (int i = 0; i<tokens.length;i++){ if (!"+".equals(tokens[i]) && !"-".equals(tokens[i]) && !"*".equals(tokens[i]) && !"/".equals(tokens[i])){ stack[index++] = Integer.parseInt(tokens[i]); }else { b = stack[--index]; a = stack[--index]; switch (tokens[i]){ case "+": stack[index++] = a + b; break; case "-": stack[index++] = a - b; break; case "*": stack[index++] = a * b; break; case "/": stack[index++] = a / b; break; default: break; } } } return stack[--index]; } }
所以空间复杂度为O(1)的做法:
提交完,看了时间反而比用int数组的花的多,而且消耗内存也没有降下了,估计是int和string两个花了双倍内存,笑死了,想法是好的,但是没有什么卵用。
//不借助辅助空间的做法 //执行用时:5 ms, 在所有 Java 提交中击败了94.04%的用户 //内存消耗:41.5 MB, 在所有 Java 提交中击败了15.26%的用户 class Solution { public int evalRPN(String[] tokens) { if (tokens.length == 1 ){ return Integer.parseInt(tokens[0]); } int a,b,index = 0; for (int i = 0; i<tokens.length;i++){ if (!"+".equals(tokens[i]) && !"-".equals(tokens[i]) && !"*".equals(tokens[i]) && !"/".equals(tokens[i])){ tokens[index++] = tokens[i]; }else { b = Integer.parseInt(tokens[--index]); a = Integer.parseInt(tokens[--index]); switch (tokens[i]){ case "+": tokens[index++] = (a + b)+""; break; case "-": tokens[index++] = (a - b)+""; break; case "*": tokens[index++] = (a * b)+""; break; case "/": tokens[index++] = (a / b)+""; break; default: break; } } } return Integer.parseInt(tokens[--index]); } }