【剑指Offer】滑动窗口的最大值(笔试&面试解法)

笔试解法:暴力求解,时间复杂度为O(N*k)

 1 class Solution {
 2     public int[] maxSlidingWindow(int[] nums, int k) {
 3         if(nums == null || nums.length == 0){
 4             return new int[nums.length];
 5         }
 6         int[] ans = new int[nums.length-k+1];
 7         for(int i = 0; i < nums.length-k+1; i++){
 8             int max = Integer.MIN_VALUE;
 9             for(int j = i; j < i+k; j++){
10                 max = Math.max(max,nums[j]);
11             }
12             ans[i] = max;
13         }
14         return ans;
15     }
16 }

 

面试解法:利用双端队列来实现窗口最大值的更新,在队列中存放数组下标。时间复杂度为O(N)

双端队列始终让队头元素是窗口中的元素的最大值的下标:nums[i]的值和队尾元素比较,如果nums[i]的值比队尾元素大,则队尾元素弹出,直到遇到一个nums[i]的值小于等于队尾,nums[i]加入队尾。

随着窗口的滚动,双端队列中的队头又可能会过期,如果队头下标等于 i-k ,说明已经过期了,直接弹出队头。

当 i >= k-1的时候,即出现了新的窗口,将队头下标对应的值加入到ans数组中。

 1 class Solution {
 2     public int[] maxSlidingWindow(int[] nums, int k) {
 3         if(nums == null || nums.length == 0){
 4             return new int[nums.length];
 5         }
 6         LinkedList<Integer> maxQueue = new LinkedList<>();
 7         int[] ans = new int[nums.length-k+1];
 8         int index = 0;
 9         for(int i = 0; i < nums.length; i++){
10             //队尾元素小于数组元素 立即弹出 始终保持队头元素最大
11             while(!maxQueue.isEmpty() && nums[maxQueue.peekLast()]<nums[i]){
12                 maxQueue.pollLast();
13             }
14             //队尾元素较大 则加入队列做跟班
15             maxQueue.add(i);
16             //判断队头元素是否过期 过期则弹出
17             if(maxQueue.peekFirst() == i-k){
18                 maxQueue.pollFirst();
19             }
20             if(i >= k-1){
21                 ans[index++] = nums[maxQueue.peekFirst()];
22             }
23         }
24         return ans;
25     }
26 }

 

posted @ 2020-05-29 20:31  xd会飞的猫  阅读(138)  评论(0编辑  收藏  举报