代码随想录-刷题笔记
内容:
这道题给我的收获真的很大,主要是学会了一个新的数据结构。
单调队列:
单调-从名字就可以知道,要么单调递增,要么单调递减。
单调队列是从队首开始递减的一个队列,并且一定是单调递减
队首应该是第一大,依次是第二大,第三大 ....
针对滑动窗口,无非是进行遍历,使用双指针, 一个为start , 一个为 end
二者分别代表窗口的起点和终点,距离是k 每次要进行的是 nums[end]入队, nums[start]出队 .
滑动窗口问题解决了,每次我们获取队列当中的最大值不就解决问题了吗 .
获取最大值,需要请出我们的 单调队列 了
单调队列也有问题,就是无法保证队列的完整信息, 只能保证最大值一定存在, 这不是完美的切合我们的问题了嘛!
下面的代码注释部分给出单调队列的详解
代码如下:
class Solution {
public class MyQueue{
//使用双端队列,该数据结构更适合实现单调队列,因为单调队列每次要跟队尾进行比较,如果比队尾大,那么队尾需要出队.
public Deque<Integer> queue = new LinkedList<>();
public void pop(int val) {
if(!queue.isEmpty() && queue.peekFirst() == val) {
queue.removeFirst();
}
}
public void push(int val) {
//跟队尾比较
while(!queue.isEmpty() && val > queue.peekLast()) {
queue.removeLast();
}
queue.addLast(val);
}
public int front(){
return queue.peekFirst();
}
}
public int[] maxSlidingWindow(int[] nums, int k) {
List<Integer> result = new ArrayList<>();
MyQueue queue = new MyQueue();
for(int i = 0 ; i < k ; i++) {
queue.push(nums[i]);
}
result.add(queue.front());
//遍历即可,实际上end-k暗含另外一个start指针~
for(int end = k ; end < nums.length ; end++) {
queue.push(nums[end]);
queue.pop(nums[end-k]);
result.add(queue.front());
}
return result.stream().mapToInt(Integer::intValue).toArray();
}
}
总结:
单调队列,单调栈,对于解决特化问题有奇效!