学习任务:
Leetcode 150. 逆波兰表达式求值
难度:中等
| 相关标签:栈、数组、数学
-
题目: 给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。请你计算该表达式。返回一个表示表达式值的整数。
注意:- 有效的算符为 ‘+’、‘-’、‘*’ 和 ‘/’ 。
- 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
-
思路: 遍历数组,遇到数字就加入栈中;遇到操作符,就从栈中取出两个数字进行计算,把计算结果再放入栈中
-
注意:
- 逆波兰表达式相当于是二叉树中的后序遍历
- – 和/ 需要注意参数顺序
-
代码:
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for (String s : tokens) {
if ("+".equals(s)) {
stack.push(stack.pop() + stack.pop()); // 注意 - 和/ 需要特殊处理
} else if ("-".equals(s)) {
stack.push(-stack.pop() + stack.pop());
} else if ("*".equals(s)) {
stack.push(stack.pop() * stack.pop());
} else if ("/".equals(s)) {
int temp1 = stack.pop();
int temp2 = stack.pop();
stack.push(temp2 / temp1);
} else {
stack.push(Integer.valueOf(s));
}
}
return stack.pop();
}
}
- 反思:
Leetcode 239. 滑动窗口最大值
难度:困难
| 相关标签:队列、数组、滑动窗口、单调队列、堆(优先队列)
-
题目: 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。 -
思路:
-
注意:
-
代码:
- 反思: 先看看视频,理解下解题思路;没太理解,先放过去吧,呜呜呜
Leetcode 347.前 K 个高频元素
难度:中等
| 相关标签:数组、哈希表、分治、桶排序、计数、快速选择、排序、堆(优先队列)
-
题目: 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
-
思路:
- 要统计元素出现频率:使用map来进行统计
- 对频率排序:使用一种 容器适配器就是优先级队列
- 找出前K个高频元素:要用小顶堆,因为要统计最大前k个元素,只有小顶堆每次将最小的元素弹出,最后小顶堆里积累的才是前k个最大元素
-
注意:
- 什么是优先级队列呢?
其实就是一个披着队列外衣的堆,因为优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列 - 对于堆(使用PriorityQueue实现):从队头到队尾按从小到大排就是最小堆(小顶堆),从队头到队尾按从大到小排就是最大堆(大顶堆)—>队头元素相当于堆的根节点
- 什么是优先级队列呢?
-
代码:
class Solution {
public int[] topKFrequent(int[] nums, int k) {
// 优先级队列,为了避免复杂 api 操作,pq 存储数组
// lambda 表达式设置优先级队列从大到小存储 o1 - o2 为从小到大,o2 - o1 反之
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);
// 答案数组为 k 个元素
int[] res = new int[k];
// 记录元素出现次数
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums){
map.put(num, map.getOrDefault(num, 0) + 1);
}
for (var x : map.entrySet()) { // entrySet 获取 k-v Set 集合
// 将 kv 转化成数组
int[] tmp = new int[2];
tmp[0] = x.getKey();
tmp[1] = x.getValue();
pq.offer(tmp);
// 下面的代码是根据小根堆实现的,我只保留优先队列的最后的k个,只要超出了k我就将最小的弹出,剩余的k个就是答案
if(pq.size() > k) {
pq.poll();
}
}
for (int i = 0; i < k; i++) {
res[i] = pq.poll()[0]; // 获取优先队列里的元素
}
return res;
}
}
- 反思: 先看看视频,理解下解题思路;能了解原理,自己也没写出来
总结:
- 递归的实现是栈:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因