题目:
输入是一个一维整数数组,和一个表示滑动窗口大小的整数;输出是一个一维整数数组,表
示每个时刻时的窗口内最大值。
思路:
1.利用双端队列进行操作:每当向右移动时,把窗口左端的值从队列左端剔除,把队
列右边小于窗口右端的值全部剔除。这样双端队列的最左端永远是当前窗口内的最大值。另外,
这道题也是单调栈的一种延申:该双端队列利用从左到右递减来维持大小关系。
2.遍历数组,将 数 存放在双向队列中,并用 L,R 来标记窗口的左边界和右边界。队列中保存的并不是真的 数,而是该数值对应的数组下标位置,并且数组中的数要从大到小排序。如果当前遍历的数比队尾的值大,则需要弹出队尾值,直到队列重新满足从大到小的要求。刚开始遍历时,L 和 R 都为 0,有一个形成窗口的过程,此过程没有最大值,L 不动,R 向右移。当窗口大小形成时,L 和 R 一起向右移,每次移动时,判断队首的值的数组下标是否在 [L,R] 中,如果不在则需要弹出队首的值,当前窗口的最大值即为队首的数。
结合代码注解理清思路:
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || nums.length < 2) return nums;
// 双向队列 保存当前窗口最大值的数组位置 保证队列中数组位置的数值按从大到小排序
LinkedList<Integer> queue = new LinkedList();
// 结果数组
int[] result =new int[nums.length-k+1];
// 遍历nums数组
for (int i = 0; i < nums.length; i++){
// 保证从大到小 如果前面数小则需要依次弹出,直至满足要求
while (!queue.isEmpty() && nums[queue.peekLast()] <= nums[i]){
queue.pollLast();
}
// 添加当前值对应的数组下标
queue.addLast(i);
// 判断当前队列中队首的值是否有效
if (queue.peek() <= i-k){
queue.poll();
}
// 当窗口长度为k时 保存当前窗口中最大值
if (i+1 >= k){
result[i+1-k] = nums[queue.peek()];
}
}
return result;
}
}