方法一:
创建 一个队列 保证加入到队列的数据按照从大到小排列
当数据需要插入队列时 和队列的最后的数据 进行比较 如果队列最后的数据 比当前值小 就说明这个数据一定不是这窗口的最大值 就把它删除掉 直到遇到 大于等于当前值的数据 加入到 队列的最后
如果队列头的数据 已经不在当前窗口时 就去除掉 队列头的数据 直到 队列头是处于当前窗口
public static int[] maxSlidingWindow(int[] nums, int k) {
if (nums.length == 1) {
return nums;
}
int len = nums.length - k + 1;
//存放结果元素的数组
int[] res = new int[len];
int num = 0;
//自定义队列
MyQueue myQueue = new MyQueue();
//先将前k的元素放入队列
for (int i = 0; i < k; i++) {
myQueue.add(nums[i]);
}
res[num++] = myQueue.peek();
for (int i = k; i < nums.length; i++) {
//滑动窗口移除最前面的元素,移除是判断该元素是否放入队列
myQueue.poll(nums[i - k]);
//滑动窗口加入最后面的元素
myQueue.add(nums[i]);
//记录对应的最大值
res[num++] = myQueue.peek();
}
return res;
}
//自定义数组
class MyQueue {
Deque<Integer> deque = new LinkedList<>();
//弹出元素时,比较当前要弹出的数值是否等于队列出口的数值,如果相等则弹出
//同时判断队列当前是否为空
void poll(int val) {
if (!deque.isEmpty() && val == deque.peek()) {
deque.poll();
}
}
//添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出
//保证队列元素单调递减
//比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2
void add(int val) {
while (!deque.isEmpty() && val > deque.getLast()) {
deque.removeLast();
}
deque.add(val);
}
//队列队顶元素始终为最大值
int peek() {
return deque.peek();
}
}
方法二
和方法一类似
只不过队列存放的是符合队列要求的 索引值;
public static int[] maxSlidingWindow(int[] nums, int k) {
int[] res = new int[nums.length - k + 1];
ArrayDeque<Integer> queue = new ArrayDeque<>();
int n = 0;
for (int i = 0; i < nums.length; i++) {
while (!queue.isEmpty() && queue.peek() < i - k + 1){
queue.poll();
}
while (!queue.isEmpty() && nums[i] > nums[queue.peekLast()]){
queue.pollLast();
}
queue.add(i);
if (i >= k - 1)
res[n ++ ] = nums[queue.peek()];
}
return res;
}