package Leetcode; import java.util.LinkedList; /** * 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。(时间复杂度限制) */ public class test239 { public static void main(String[] args) { int []nums={1,3,-1,-3,5,3,6,7}; int k=3; int []result=maxSlidingWindow(nums, k); int x=0; } //双向链表存储最大值index位置 ///遍历数组,将 数 存放在双向队列中,并用 L,R 来标记窗口的左边界和右边界。队列中保存的并不是真的 数,而是该数值对应的数组下标位置, // 并且数组中的数要从大到小排序。如果当前遍历的数比队尾的值大,则需要弹出队尾值,直到队列重新满足从大到小的要求。刚开始遍历时, // L 和 R 都为 0,有一个形成窗口的过程,此过程没有最大值,L 不动,R 向右移。当窗口大小形成时,L 和 R 一起向右移,每次移动时, // 判断队首的值的数组下标是否在 [L,R] 中,如果不在则需要弹出队首的值,当前窗口的最大值即为队首的数。 // R=i,L=k-R。由于队列中的值是从大到小排序的,所以每次窗口变动时,只需要判断队首的值是否还在窗口中就行了。 // 解释一下为什么队列中要存放数组下标的值而不是直接存储数值,因为要判断队首的值是否在窗口范围内,由数组下标取值很方便,而由值取数组下标不是很方便。 public static int[] maxSlidingWindow(int[] nums, int k) { if(nums==null||nums.length<2){ return nums; } LinkedList<Integer> queue=new LinkedList<>(); int []result=new int[nums.length-k+1]; for(int i=0;i<nums.length;i++){ while(!queue.isEmpty()&&nums[queue.peekLast()]<=nums[i]){ queue.pollLast(); } queue.add(i); if(queue.peek()<=i-k){ queue.poll(); } if(i+1>=k){ result[i+1-k]=nums[queue.peek()]; } } return result; } }