Sliding Window Maximum

来源:互联网 发布:C语言的算术表达式 编辑:程序博客网 时间:2024/05/16 01:57

Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.

For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.

Window position                Max---------------               -----[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

Therefore, return the max sliding window as [3,3,5,5,6,7].

Note:
You may assume k is always valid, ie: 1 ≤ k ≤ input array’s size for non-empty array.

思路:先确定结果数组res的长度大小,很显然,res的长度应该为nums.length-k+1; 用一个双端队列来保存有可能成为滑动窗口的最大数值。
以{2, 3, 4, 2,6,2, 5, 1} 和k=3 进行分析

  1. 数组的第一个数字是2,把它存入队列中,第二个数字为3,由于它比第一个数字2大,此时2不可能成为当前滑动窗口中的最大值,那么删除2,把3加入队列,此时队列中只有一个数字为3。对于数组中第3个数字4,它比队列中的数字大,那么队列中的数字不能成为当前滑动窗口的最大数值,因此,删除队列中的数字3,然后添加数字4,此时第一个滑动窗口的最大数字就是队列的最前面的数字。把队列最前面的数字添入结果数组中,即第一个滑动窗口的最大值找到了,接下来就开始移动滑动窗口了。
  2. 接下来处理第四个数字2, 2比队列中的数字4小,有可能当滑动窗口滑动时,把4给移出去,2有可能成为当前滑动窗口中最大的数字,所以2要添加进队列中,此时队列中的数字为4和2。其中最大值4仍然位于队列的头部,4为第二个滑动窗口的最大值。
  3. 下一个数字是6,由于6比队列中的数字都大,所以,队列中的数字已经不可能成为当前滑动窗口的最大值,把4和2都给移出去,并把6添加进去,此时第3个滑动窗口的最大值已经找到了。
  4. 下一个数字是2,2比6小,在6被滑动窗户滑动时移出去之后,2有可能是下一个滑动窗口的最大值,所以将2添加到队列,此时队列中的数字是6和2,其中最大值6仍然位于队列的头部,此时第四个滑动窗口的最大值6已经被找到了
  5. 下一个数字是5,5比2大,比6小,那么删除2,将5放在6的后面。此时第五个滑动窗口的最大值为6
  6. 最后一个数字为1,1比5小,直接放在5的后面,但是此时队列最前面的值为6,但是第六个滑动窗口(2,5,1)已经不包含6了,所以6对于当前滑动窗口来说已经无效,需要把6给移出去,此时队列最前面的数是5,5 是有效的,最后一个滑动窗口的最大值是5.

    注:数组的最后一个数字是1,把1添加进去队列。这个时候6已经对于当前滑动窗口是无效的,但是怎么判断6的无效的呢,当当前判断的数字与队列最前面的数字之差大于或者等于滑动窗口的大小时,那么该数字是无效的,这么说了,为了判断队列前面的数字是不是有效的,所以在队列中我们应该存储的是元素的下标,而不是元素的值。

public class Solution {    public int[] maxSlidingWindow(int[] nums, int k) {        int[] res=new int[0];        int pos=0;        if(nums.length==0)  return res;        if(k<=0 || k>nums.length) return res;        res=new int[nums.length-k+1];        ArrayDeque<Integer> queue=new ArrayDeque<Integer>();        for(int i=0;i<k;i++)        {           while(queue.size()!=0 && nums[i]>nums[queue.getLast()])                queue.removeLast();                queue.addLast(i);        }      if(k==nums.length)           { res[pos++]=nums[queue.peekFirst()];              return res;           }        for(int i=k;i<nums.length;i++)        {            res[pos++]=nums[queue.peekFirst()];             while(queue.size()!=0 && nums[i]>nums[queue.getLast()])                queue.removeLast();             if(queue.size()!=0 && queue.getFirst()+k<=i)                queue.removeFirst();                queue.addLast(i);        }        res[pos]=nums[queue.peekFirst()];        return res;    }}
0 0
原创粉丝点击