解法都在代码里,不懂就留言或者私信
官方定级hard难度,其实是medium,确实字节考过
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if(nums.length == 1) {return new int[]{nums[0]};}/**我们要返回的是一个数组,这个窗口从遍历到第k个元素(下标k-1)的时候就形成了,所以最后返回结果的长度是n-(k-1)=n-k+1 */int[] ans = new int[nums.length - k + 1];/**看题意就知道肯定是滑动窗口了,题目标题就是滑动窗口的最大值,这还有啥说的我们先定义一个窗口,left表示窗口的左边界(包含),right表示窗口的右边界(不包含)窗口的有效范围是[left, right)的前闭后开区间,初始窗口是[0,0)表示窗口内没有值 */int left = 0;int right = 0;/**我们使用双向链表来表示这个窗口,我们这里只求最大值,所以定义一个链表即可这里链表里存的是下标 */LinkedList<Integer> maxWindow = new LinkedList<>(); /**遍历数组统计,right每次都++,left只有窗口形成之后才++,所以如果有越界这回事,right肯定比left早越界所以无需判断left是否越界,这里写<=是为了收集最后一个窗口的最大值*/while(right <= nums.length) {/**下面就是要处理加入right之前窗口已经形成的情况了,如果加right之前窗口已经够k个了,那left位置应该淘汰 原来的窗口是[left, right),有效长度是right-left*/if(right - left == k) {/**既然窗口够了,那搜集一波最大值 */ans[left] = nums[maxWindow.peekFirst()];/**如果left位置是当前窗口最大值,那它出去了最大值就变了 */if(left == maxWindow.peekFirst()) {/**把最大值去掉,以后的最大值还是pollFirst */maxWindow.pollFirst();} /**left向右移动,原来的left出窗口 */left ++;}/**如果right已经越界了,那就没有必要进行剩下的了 */if(right == nums.length) {break;}/**我们当前不管窗口形成还有没有形成,right位置都要入窗口(入链表或者说入队列) 因为链表中的元素是按照从first到last越来越小排列的,所以窗口不为空并且窗口中有小于等于(这里要注意的是等于也要淘汰,等于淘汰的理由是你在我前面肯定出窗口的时间早于我,即便都不出去,你可以作为最大值的情况我也可以,你早点出去我更是比你更适合当最大值)就淘汰*/while(!maxWindow.isEmpty() && nums[maxWindow.peekLast()] <= nums[right]) {maxWindow.pollLast();}/**把小于等于last位置的都淘汰,last位置就可以入窗口了*/maxWindow.addLast(right);/**不管窗口够不够,right肯定要右移的 */right ++;}return ans;}
}