LeetCode - 150. Evaluate Reverse Polish Notation 逆波兰表达式求值
什么是逆波兰表达式?逆波兰表达式也称为后缀表达式,我们平常写出来的数学表达式大多为中缀表达式,如(1+2) * (3+4)。如果把这个画成树状图,就可以遍历得出逆波兰表达式。 中缀表达式需要加括号才能正确运算,但是后缀表达式就可以不用括号表示,用顺序就能计算出正确结果,这个计算过程就是由栈来实现的。
解题思路:遍历一个逆波兰表达式,如果遇见数字则加入栈中,如果两个数字遇见了一个操作符,就在栈中消除合成一个数字,再加入到栈中,最后的结果也就是栈中的最后唯一一个元素。其实和1047题相邻字符删除有些类似,栈就很适合用来解决这类问题。同时需要注意的是因为逆波兰表达式的遍历方式是左右中,因此在减和除的操作应该是第二个减或除以第一个数字。
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> st = new Stack<>();
for (String c : tokens) {
if (c.equals("+")|| c.equals("-") || c.equals("*") || c.equals("/")) {
//for operators
int num1 = st.pop();
int num2 = st.pop();
int res = 0;
switch (c) {
case "+" -> res = num1 + num2;
case "-" -> res = num2 - num1; //左右中遍历
case "*" -> res = num1 * num2;
case "/" -> res = num2 / num1;
}
st.add(res);
} else {
//for numbers
st.add(Integer.parseInt(c));
}
}
return st.pop();
}
}
LeetCode - 239. Sliding Window Maximum 滑动窗口最大值
解题目标:给定一个数组以及滑动窗口大小k,求出每一个滑动窗口内的最大值
(待更新...)
LeetCode - 347. Top K Frequent Elements 前K个高频元素
解题目标:给定数组和正整数k,返回前k个高频元素。
解题思路:这道题有两个难点,一个是如何求每个元素出现的次数,还有就是如何对频率进行排序。对于频率的记录可以用Map结构,key存储元素,value存储出现次数。大顶堆和小顶堆可以用来求出前k个高频元素。Java中的优先级队列可以直接实现堆的逻辑。
class Solution {
public int[] topKFrequent(int[] nums, int k) {
//pq 默认为小顶堆,o2[1]-o1[1]则就是大顶堆
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o2[1] - o1[1]);
HashMap<Integer, Integer> hm = new HashMap<>();
int[] res = new int[k];
//record frequencies to HashMap
for (int num : nums) {
hm.put(num, hm.getOrDefault(num, 0) + 1);
}
//add element (entry) to pq
for (var x : hm.entrySet()) {
int[] temp = new int[2];
temp[0] = x.getKey();
temp[1] = x.getValue();
pq.offer(temp);
}
//get root
for (int i = 0; i < k; i++) {
res[i] = pq.poll()[0];
}
return res;
}
}
在第一次写的时候用的是大顶堆,大顶堆的思路必须是加入所有的元素最后再依次poll到结果集中,但是我们无法确定元素的个数,但是小顶堆的思路可以在添加的时候同时剔除最小的元素,这样可以保证优先级队列的长度永远最大是k吗,堆排序的时间复杂度为logk,而大顶堆排序则需要logn。以下是小顶堆的实现代码:
class Solution {
public int[] topKFrequent(int[] nums, int k) {
//pq 默认为小顶堆,o2[1]-o1[1]则就是大顶堆
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);
HashMap<Integer, Integer> hm = new HashMap<>();
int[] res = new int[k];
//record frequencies to HashMap
for (int num : nums) {
hm.put(num, hm.getOrDefault(num, 0) + 1);
}
//add element (entry) to pq
for (var x : hm.entrySet()) {
int[] temp = new int[2];
temp[0] = x.getKey();
temp[1] = x.getValue();
pq.offer(temp);
// once pq is longer than k, remove root element(smallest)
if (pq.size() > k) {
pq.poll();
}
}
for (int i = k-1; i >= 0; i--) {
res[i] = pq.poll()[0];
}
return res;
}
}