题目描述
给定一个数组
nums
和滑动窗口的大小k
,请找出所有滑动窗口里的最大值。
示例:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
暴力解法(超出时间限制QAQ)
每次更新队列寻找最大值
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int len = nums.length;
Queue<Integer> queue = new LinkedList<>();
int max = Integer.MIN_VALUE;
int[] res = new int[len-k+1];
for(int i = 0;i<k;i++){
queue.offer(nums[i]);
}
for(int i = k;i<len;i++){
res[i-k] = queueMax(queue);
queue.offer(nums[i]);
queue.poll();
}
res[len-k] = queueMax(queue);
return res;
}
private int queueMax(Queue<Integer> queue){
int max = Integer.MIN_VALUE;
Queue<Integer> temp = queue;
for(int i =0;i<queue.size();i++){
if(max<temp.peek()){
max = temp.peek();
}
temp.offer(temp.poll());
}
return max;
}
}
官方解法
算法流程:
-
初始化: 双端队列 dequedeque ,结果列表 resres ,数组长度 nn ;
-
滑动窗口: 左边界范围 i ∈[1−k,n−k] ,右边界范围j∈[0,n−1]
-
若 i > 0 且 队首元素 deque[0] ==被删除元素nums[i−1] :则队首元素出队;
-
删除 deque 内所有<nums[j] 的元素,以保持 deque递减;
-
将 nums[j] 添加至 deque尾部;
-
若已形成窗口(即 i≥0 ):将窗口最大值(即队首元素deque[0] )添加至列表 res ;
3. 返回值: 返回结果列表 res ;
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length == 0 || k == 0) return new int[0];
Deque<Integer> deque = new LinkedList<>();
int[] res = new int[nums.length - k + 1];
for(int j = 0, i = 1 - k; j < nums.length; i++, j++) {
// 删除 deque 中对应的 nums[i-1]
if(i > 0 && deque.peekFirst() == nums[i - 1])
deque.removeFirst();
// 保持 deque 递减
while(!deque.isEmpty() && deque.peekLast() < nums[j])
deque.removeLast();
deque.addLast(nums[j]);
// 记录窗口最大值
if(i >= 0)
res[i] = deque.peekFirst();
}
return res;
}
}