239.滑动窗口最大值
题目链接:力扣
声明一个队列,可以使用 ArrayDeque 也可以是 LinkedList 用来保存下标
- 先循环删除队列中超过窗口范围的下标
- 然后判断循环删除不符合条件的值:判断当前值是否大于之前保存下标的值,如果大于就删除之前的下标,说白了就是留当前区间最大值的下标在队列中,并保持在开头。
- 然后每次范围变更,只需要取队列开头的值就可以了。
使用单调对联,ArrayDeque 可以替换成 LinkedList,不过前者更省内存。
public int[] maxSlidingWindow(int[] nums, int k) {
ArrayDeque<Integer> deque = new ArrayDeque<>();
int n = nums.length;
int[] res = new int[n - k + 1];
int idx = 0;
for (int i = 0; i < n; i++) {
// 根据题意,i为nums下标,是要在[i - k + 1, i] 中选到最大值,只需要保证两点
// 1.队列头结点需要在[i - k + 1, i]范围内,不符合则要弹出
while (!deque.isEmpty() && deque.peek() < i - k + 1) {
deque.poll();
}
// 2.既然是单调,就要保证每次放进去的数字要比末尾的都大,否则也弹出
while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {
deque.pollLast();
}
deque.offer(i);
// 因为单调,当i增长到符合第一个k范围的时候,每滑动一步都将队列头节点放入结果就行了
if (i >= k - 1) {
res[idx++] = nums[deque.peek()];
}
}
return res;
}
暴力破解,时间复杂度 N * K,会被一个巨长的示例超时
public static int[] maxSlidingWindow(int[] nums, int k) {
int[] result = new int[nums.length - k + 1];
int start = 0;
LinkedList<Integer> window = new LinkedList();
for (int i = 0; i < nums.length; i++) {
window.push(nums[i]);
if (window.size() > k) {
window.removeLast();
}
if (window.size() >= k) {
int temp = Integer.MIN_VALUE;
for (Integer integer : window) {
temp = Math.max(integer, temp);
}
result[start++] = temp;
}
}
return result;
}
347.前 K 个高频元素
题目链接:力扣
使用 PriorityQueue 优先队列解决,该类基于二叉树实现,用法:
[PriorityQueue]:Java中PriorityQueue的用法_GitKid的博客-CSDN博客
使用PriorityQueue - 廖雪峰的官方网站
解题代码:
public int[] topKFrequent(int[] nums, int k) {
int[] result = new int[k];
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
PriorityQueue<int[]> pq = new PriorityQueue<>((p1, p2) -> p2[1] - p1[1]);
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
pq.add(new int[]{entry.getKey(), entry.getValue()});
}
for (int i = 0; i < k; i++) {
result[i] = pq.poll()[0];
}
return result;
}
总结
才知道 Java 内置了这么多数据类型。