引入
做LeetCode题目:滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。返回 滑动窗口中的最大值 。https://leetcode-cn.com/problems/sliding-window-maximum
历时几个星期,用自己朴素的想法,解题都对,但是超时间。
查看题解,要用到一些队里的知识。特此在本文记录一下这方面的知识。队列,堆栈的使用,推荐就使用Java封装好的类,去使用就好,否则自己来写,往往一头雾水,还没有效率,我们就大胆的站在巨人的肩膀上,直接使用这些底层类,而不用去管底层的实现。如果每次纠结,想自己来实现,真的是一言难尽啊
单词学习
添加元素 | 删除头顶元素 | 读头顶元素 |
---|---|---|
add | remove | element |
offer | poll | peek |
push | pop | first |
peek 的意思有瞥见
poll 头顶的意思
https://blog.csdn.net/devnn/article/details/82716447
使用示例
一、优先队列
// 优先队列 (堆)
PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(new Comparator<Object>() {
// 重写比较方法,怎么判断优先
public int compare(Object pair1, Object pair2) {
return pair1[0] != pair2[0] ? pair2[0] - pair1[0] : pair2[1] - pair1[1];
}
});
priorityQueue.offer(new int[]{nums[i], i}); // 添加
priorityQueue.peek()[0]; // 查看头顶元素
priorityQueue.poll(); // 删除头顶元素
原文连接题解:
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
PriorityQueue<int[]> priorityQueue = new PriorityQueue<int[]>(new Comparator<int[]>() {
public int compare(int[] pair1, int[] pair2) {
return pair1[0] != pair2[0] ? pair2[0] - pair1[0] : pair2[1] - pair1[1];
}
});
for (int i = 0; i < k; ++i) {
priorityQueue.offer(new int[]{nums[i], i});
}
int[] ans = new int[n - k + 1];
ans[0] = priorityQueue.peek()[0];
for (int i = k; i < n; ++i) {
priorityQueue.offer(new int[]{nums[i], i});
while (priorityQueue.peek()[1] <= i - k) {
priorityQueue.poll();
}
ans[i - k + 1] = priorityQueue.peek()[0];
}
return ans;
}
二、单调队列
Deque deque = new LinkedList(); // 记录最大值的下标
deque.offerLast();
deque.isEmpty();
deque.peekLast();
deque.pollLast();
// 单调队列,单调递减的队列,头上的是最大的
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
Deque<Integer> deque = new LinkedList<Integer>(); // 记录最大值的下标
for (int i = 0; i < k; ++i) {
while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
deque.pollLast();
}
deque.offerLast(i);
}
int[] ans = new int[n - k + 1];
ans[0] = nums[deque.peekFirst()];
for (int i = k; i < n; ++i) {
while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
deque.pollLast();
}
deque.offerLast(i);
while (deque.peekFirst() <= i - k) { // 最大值超过左边界了
deque.pollFirst(); // 移除最大值,第二大值变最大值了。
}
ans[i - k + 1] = nums[deque.peekFirst()];
}
return ans;
}
三、稀疏表(Sparse Table)求区间最值问题
预处理
递推
prefixMax[i] 从0到i之间的最大值
suffixMax[i] 从i 到 length的最大值
那么 Max[i] = max{ prefixMax[i] ,suffixMax[i]}