Leetcode面试经典150题-239.滑动窗口最大值

解法都在代码里,不懂就留言或者私信

官方定级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;
    }
}

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值