239. 滑动窗口最大值
困难
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入: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 <= nums.length <= 105
-
-104 <= nums[i] <= 104
-
1 <= k <= nums.length
详解:单调递减队列。 核心思想:越靠后(因为越靠后越年轻, 在后面可以被压榨的时间越长)&&越大的数(因为本题选最大值)更有价值,他们不应该被裁。所以在这里维护一个单调递减队列, 后面加入的数只有一种情况就是:新加入的数能比老员工创造更多的价值(更大)。里面的数据如:13、11、9、5、1、0
class Solution { public int[] maxSlidingWindow(int[] nums, int k) { // 开了家公司 LinkedList<Integer> queue = new LinkedList<>(); int n = nums.length; // 结果 int[] res = new int[n - k + 1]; int j = -1; // 公司开始运行了,招聘员工ing... for(int i = 0; i < n; i ++){ // 公司还有员工的情况下,发现了一个新加入的员工,他不仅年轻(靠后),能力还更强(数更大), 那就从kpi低的老员工开始优化 // 观察了新员工的简历,先把能力比新员工低的老员工优化了(也就是后面的) while(!queue.isEmpty() && nums[i] >= nums[queue.peekLast()]){// 排名靠后的老员工 queue.pollLast(); } // 优化完老员工(当然队列中不存在元素的话就没法优化了),再加入新员工,此时新员工前面全是前辈(数值比他大) queue.addLast(i); // 判断能力最强的老员工是否到达35岁(是否在窗口的最后一个位置前),精力不行的话赶紧优化掉 if(queue.peek() <= i - k){ queue.poll(); } // 如果员工的数量已经可以评出优秀员工了,就选出第一名(其实就是第 i == k - 1 后开始的, 因为i的下标从0开始) if(i - k + 1 >= 0){ res[++ j] = nums[queue.peek()]; } } return res; } }