150. 逆波兰表达式求值
用栈做,遍历tokens,将数字转为Integer类型依次入栈。每遇见一个符号,从栈顶取出两个,进行运算后将结果入栈,最后栈顶元素即为所求
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new LinkedList<>();
for(String s : tokens){
if("+".equals(s) || "-".equals(s) || "*".equals(s) || "/".equals(s)){
int num2 = stack.pop();
int num1 = stack.pop();
if("+".equals(s)){
stack.push(num1 + num2);
}else if("-".equals(s)){
stack.push(num1 - num2);
}else if("*".equals(s)){
stack.push(num1 * num2);
}else{
stack.push(num1 / num2);
}
}else{
stack.push(Integer.parseInt(s));
}
}
return stack.pop();
}
}
———————————————————————————————————————————
239. 滑动窗口最大值
单调队列,一个双端队列。
单调队列的队首元素始终为最大值。
遍历元素并加入队列的过程:先构建第一个窗口的单调队列。之后每向后移动一次窗口,就将新加入窗口的元素加入队列中。
在加入队列时,当队尾元素小于要加入的新元素时(while),就将队尾元素出队,最后将新元素加入队尾。
在每次移动窗口后,若队首元素在窗口外了,需要将队首元素出队(while)。
注意因为要移动窗口,因此队列中存储的元素应该是数组下标 。
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
Deque<Integer> deque = new LinkedList<>();
int[] res = new int[nums.length - k + 1];
Arrays.fill(res, Integer.MIN_VALUE);
for(int i = 0; i < nums.length; i++){
//处理窗口外的元素
while(!deque.isEmpty() && deque.peekFirst() < i - k + 1){
deque.pollFirst();
}
while(!deque.isEmpty() && nums[deque.peekLast()] <= nums[i]){
deque.pollLast();
}
deque.offerLast(i);
if(i >= k - 1){
res[i - k + 1] = nums[deque.peekFirst()];
}
}
return res;
}
}
——————————————————————————————————————————
347. 前 K 个高频元素
优先队列
其实就是大顶堆、小顶堆
java的优先队列使用PriorityQueue实现,可以传入比较器自行定义为大小顶堆
优先队列中的元素是一个二维的数组,数组的元素分别是num和出现的频率
这里大顶堆实现
class Solution {
public int[] topKFrequent(int[] nums, int k) {
PriorityQueue<int[]> priorityQueue = new PriorityQueue<>((o1, o2) -> o2[1] - o1[1]);
Map<Integer, Integer> map = new HashMap<>();
for (int i : nums) {
map.put(i, map.getOrDefault(i, 0) + 1);
}
for (Map.Entry<Integer, Integer> integerIntegerEntry : map.entrySet()) {
priorityQueue.add(new int[]{integerIntegerEntry.getKey(), integerIntegerEntry.getValue()});
}
int[] res = new int[k];
for(int i = 0; i < k; i++){
res[i] = priorityQueue.poll()[0];
}
return res;
}
}