题目:150. 逆波兰表达式求值
给你一个字符串数组 tokens
,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'
、'-'
、'*'
和'/'
。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
示例 1:
输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:
输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:
输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
输出:22
解释:该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
代码:
class Solution { public int evalRPN(String[] tokens) { Stack<Integer> stack = new Stack<>(); for(String s : tokens) { if(s.equals("+")||s.equals("-")||s.equals("*")||s.equals("/")) { int num2 = stack.pop(); int num1 = stack.pop(); if(s.equals("+")) stack.push(num1 + num2); if(s.equals("-")) stack.push(num1 - num2); if(s.equals("*")) stack.push(num1 * num2); if(s.equals("/")) stack.push(num1 / num2); }else { stack.push(Integer.parseInt(s)); } } return stack.pop(); } }
思路:
此题思路为,遍历字符串数组,遇到数字就入栈,遇到符号就出栈两个数字(注意num1 num2顺序),然后进行运算后再将结果压入栈,最后栈中的唯一元素即为结果。
题目:239. 滑动窗口最大值
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
示例 2:
输入:nums = [1], k = 1
输出:[1]
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length
代码:
class Solution { class MyQueue { Deque<Integer> deque = new LinkedList<>(); //只有val与peek()值相等时才pop void poll(int val) { if(!deque.isEmpty() && val == deque.peek()) { deque.poll(); } } //添加元素时要pop所有 在val前且小于val的值 void add(int val) { while(!deque.isEmpty() && val > deque.getLast()) { deque.removeLast(); } deque.add(val); } //队列的队顶元素始终是最大值 int peek() { return deque.peek(); } } public int[] maxSlidingWindow(int[] nums, int k) { if(nums.length == 1) return nums; //存放结果 int[] res = new int[nums.length - k + 1]; int num = 0; //自定义队列 MyQueue myQueue = new MyQueue(); //先将目前窗口元素(前k个)放入队列 for(int i = 0;i<k;i++) { myQueue.add(nums[i]); } //放入后 当前窗口的最大值即为peek res[num++] = myQueue.peek(); for(int i = k;i<nums.length;i++) { myQueue.poll(nums[i-k]); myQueue.add(nums[i]); res[num++] = myQueue.peek(); } return res; } }
思路:
此题为困难题,思路为自己创建一个单调队列类,实现poll、add、peek方法。
当队列add时,只要在val前 且比val小的 都poll掉,因为维护他们没有意义了,只要有val在窗口的最大值都是val。
当队列poll时,只有当val == myQueue.peek() 时才poll,因为其他元素都在add时删除了。
队列的peek(),永远都是窗口的最大值。
完成了这个单调队列类,我们的工作就只剩遍历数组。