【每日一题-leetcode】239.滑动窗口最大值

239.滑动窗口最大值

  1. 滑动窗口最大值

难度困难290

给定一个数组 nums,有一个大小为 k *的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 *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.暴力法

思路:我们可以将滑动窗口问题抽象化,一直移动那么最后的数据格式就是一个二维数组 for for 遍历找出每次滑动窗口的最大值存储起来,就可以了。首先是确定滑动窗口的次数。k是窗口的大小,n是长度 k = 3 n = 8 移动了6 size = n - k +1 外层循环是移动次数 内层循环开始条件是 i 随着移动次数增加, k = i 终止条件为 最终移动的次数 i + k 就到数组的最后了。剩下依次判断就可以了。

时间复杂度:O(N*K) 外层k次 内层N次

空间复杂度:O(n-k+1)

   public int[] maxSlidingWindow(int[] nums, int k) {
            //参数判断
            int length = nums.length;
            if(length * k == 0){
                return new int [0];
            }
            //窗口移动的次数为length-k+1
            int [] array = new int [length-k+1];  
            for(int i=0;i<length-k+1;i++){
                int max = Integer.MIN_VALUE;
              //因为窗口每次都要移动 在i的基础上 增加 终止条件是i+k 说明到底
              //每一次loop 找出最大值
                for(int j=i;j<i+k;j++){
                    max = Math.max(max,nums[j]);
                }
               //该层的最大值
                array[i] = max;
            }
            return array;
        }

2.双端队列

思路:使用队列进行存储每次窗口的最大值的下标,如果当前值最大 那么之前的所有值就可以清空了

ps : 1 3 4 4最大 所以在这个窗口期中4一直最大 1 3 就可以出队列。

time:O(N) 队列的出队和入队是O(1) 只存在遍历n次数组中的数据

space:O(n)

private  ArrayDeque<Integer> deq = new ArrayDeque();//存储下标值 比较大小
private  int [] nums;
public int[] maxSlidingWindow(int[] nums, int k) {
    if(nums.length == 0 || k == 0){ //参数判断
        return new int [0];
    }
    int n = nums.length;   this.nums = nums;
    //存储最大值的数组
    int [] arr = new int [n-k+1];   int maxIndex = 0;
    for(int i=0;i<k;i++){
        cleanDeq(i,k);
        deq.addLast(i);
        maxIndex = nums[maxIndex] > nums[i] ? maxIndex : i;  
   }
    arr[0] = nums[maxIndex];
    for(int i = k;i<n;i++){
        cleanDeq(i,k);
        deq.addLast(i);
        arr[i-k+1] = nums[deq.getFirst()];
    }
    return arr;
}
public void cleanDeq(int i,int k){
    if(!deq.isEmpty() && deq.getFirst() == i-k){//删除前边数据较小的。或者无用数据
        deq.removeFirst();
    }
    while(!deq.isEmpty() && nums[i] > nums[deq.getLast()]){ 
      //如果当前值大于之前所有的值 则删除 
        deq.removeLast();
    }
}
posted @ 2020-04-03 16:27  qxlxi  阅读(105)  评论(0编辑  收藏  举报