滑动窗口的最大值

给定一个数组 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

分析:

  1. 维护一个双端队列,保证滑动窗口中顺序数字的从大到小排序,如果数值大的数字出现在滑动窗口的后面,那么将舍弃滑动窗口前面数值小的数字,保留数值大的数字
import java.util.Deque;
import java.util.LinkedList;
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums.length==0||k==0){
            return new int[0];
        }
        //构建一个双端队列,让其里面一直递减,保存的是窗口中最大的元素和后面比他小的
        //维持滑动窗口内数字从小到大排序,如果中间有小的,后面出来了大的,舍弃中间小的
        //如果滑动窗口移动了,出现了比当前双端队列中的最后的元素大的数,那么直接removeLast,删除掉滑动窗口的最后一个,一直删除,直到找到比当前滑动窗口新添加的元素大或相等的元素
        Deque<Integer> deque = new LinkedList<>();   
       
        int[] res = new int[nums.length-k+1];   //存储每次窗口移动时最大的元素,最后返回的值
        //i表示窗口的头,j表示窗口的尾部
        for(int j=0,i=1-k;j<nums.length;j++,i++){
            //窗口移动,deque的头是否是移动后前一个,如果是则移除deque的头部
            if(i>0&&deque.peekFirst()==nums[i-1]){
                deque.removeFirst();
            }
            //窗口移动,判断准备往双端队列尾部添加的nums[j]是否大于前面的,如果大于则删除前面的,直到不是最大的
            while(!deque.isEmpty()&&nums[j]>deque.peekLast()){
                deque.removeLast();
            }
            //窗口移动,添加元素
            deque.addLast(nums[j]);
            //i>=0时,表示窗口已经形成,给res数组,记录当前窗口中最大的值
            if(i>=0){
                res[i]=deque.peekFirst();
            }
        }
        return res;
    }
}
上一篇:1425. 带限制的子序列和


下一篇:C++ | STL 浅谈deque容器