滑动窗口的最大值

题目描述

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

提示:

你可以假设 k 总是有效的,在输入数组不为空的情况下,1 ≤ k ≤ 输入数组的大小。

解法1(不推荐)

之前在剑指offer做这个题的时候,使用优先队列构先建堆,每次清空,时间和空间复杂度都较高。

import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size)
    {
        ArrayList<Integer> result=new ArrayList<Integer>();
        if(num==null||size<=0||num.length<size)
            return result;
        PriorityQueue<Integer> queue=new PriorityQueue<Integer>(size,(x,y)->y-x);
        //lamda表达式实现降序排列
         int count=0;
            for(int i=0;i<num.length-size+1;i++)
                {
                 while(count<size)
                 {
                     queue.offer(num[i+count]);//从第i个开始的size窗口
                     count++;
                 }
                    result.add(queue.peek());
                    count=0;//计数器清空
                    queue.clear();//最大堆清空
                    
                }
        return result;
    }
}

解法2:

利用单调栈的性质,维持一个双端队列,队首存放最大的元素。添加元素时候,按照单调栈的规则添加到队列后面:当队列尾端一直小于当前元素时候,出栈,直到当前元素下雨队列尾部的元素。然后在滑动窗口向右滑动时候,需要考虑当前数组的元素如果刚好在双端队列的队首,表示已经遍历过下,需要移除队列。

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n=nums.length;
        if(n==0||k==0)
        return new int[0];
        Deque<Integer>deque=new ArrayDeque<>();//单调栈,队首存放最大元素
        int[]ans=new int[n-k+1];
        for(int i=0;i<k;i++){
            while(!deque.isEmpty()&&deque.peekLast()<nums[i])//没有形成队列的时候
            deque.removeLast();
            deque.addLast(nums[i]);
        }
        ans[0]=deque.peekFirst();
        for(int i=k;i<n;i++){
            if(deque.peekFirst()==nums[i-k])//如果nums当前遍历的元素在deque的队首,就需要从队列中移除
            deque.removeFirst();
            while(!deque.isEmpty()&&deque.peekLast()<nums[i])
            deque.removeLast();
            deque.addLast(nums[i]);
            ans[i-k+1]=deque.peekFirst();//每次滑动窗口的最大值都是在队首
        }
        return ans;
    }
}

你可能感兴趣的:(leetcode,队列)